Jump to content
Pixrael

OMG!.. help with URL SEGMENTS please!

Recommended Posts

I have a parent page (with template file) with several child pages (without template file) that are hidden and unpublished, I use them only to store information. The parent page have the url segments enabled.

When I catch the segment in the template file, works as expected for any word, but if the url segment match the property "name" of any child page, PW launch a 404 Page Not Found.. I try all combination of "hidden" and "Publish" for the child pages.

The idea is to render the data from the parent page plus the data of a child page, and get this data using an url segment (links generated dynamically) with the same name that this hidden page have.. I don't like having a template file for these child pages that only execute the render of the parent page with the information .. I want the previous solution if it possible

I was able to explain well? ...What happen here?

Share this post


Link to post
Share on other sites

I found why :-(

https://processwire.com/docs/tutorials/how-to-use-url-segments/page2

"You can use URL segments on any page where your template settings allow, regardless of whether it has children or not. Should there be a child page that has the same name as a URL segment that the parent page's template is looking for, the pages in the tree always have precedence. Meaning, URL segments only apply if the requested URL did not resolve to an actual page. As a result, you should avoid using URL segments where you think the page names and URL segments could collide"

Share this post


Link to post
Share on other sites

maybe you can use the page id as url segment? then you do not have the name conflict (or at least you would only have it if a page with the name of another page's id exists, what should be at least very unlikely or if you take care of this would be impossible).

ps: or you take an url segment like #getcontent#123 and then you strip off the #getcontent# part and request the page's content by the id

Share this post


Link to post
Share on other sites

abdus: I think your solution don't resolve my problem, I'm still have the match between both urls (segment and existing page), this option only allow me to auto generate the children names, this is not my case.

bernhard: this is a correct solution, in the first instance I not use it because the SEO.. maybe I need to use it.. :-(

Another solution should be put the "child pages" under another parent (empty template) only for hold it and to avoid conflicts

Thanks guys for your time!

Share this post


Link to post
Share on other sites
1 minute ago, Pixrael said:

bernhard: this is a correct solution, in the first instance I not use it because the SEO.. maybe I need to use it.. :-(

then i didn't understand your question, because my solution would have nothing to do with seo ;)

Share this post


Link to post
Share on other sites

my path will change from:

domain.com/support/codes/wall-mount-mini-split

domain.com/support/codes/light-commercial-split

to

domain.com/support/codes/1087

domain.com/support/codes/1101

Share this post


Link to post
Share on other sites

i know that this would change

1 hour ago, Pixrael said:

The idea is to render the data from the parent page plus the data of a child page, and get this data using an url segment (links generated dynamically) with the same name that this hidden page have.. I don't like having a template file for these child pages that only execute the render of the parent page with the information .. I want the previous solution if it possible

but i thought you maybe request only some content via ajax or the like and populate areas in your parent page's template. i don't really get what you are trying to achieve and what the problem would be with a template for your child pages... :) but it's late here ;)

Share this post


Link to post
Share on other sites

If pages are not public, then you wouldnt need to worry about SEO.

Page name format works for pages created in the future, but for the current pages you can do:

$codes = wire()->pages('template=code');

foreach ($codes as $c) {
    // wall-mount-mini-split becomes code--wall-mount-mini-split
    $replacement = "code--{$c->name}";
    $c->of(false);
    $c->setName($replacement);
    $c->save();
}

And in your template, where you check urlSegments:

if($input->urlSegment1) {
    if ($input->urlSegment2) throw new Wire404Exception();

    $codeName = "code--{$input->urlSegment1}";
    $codeName = $sanitizer->pageName($codeName);

    $code = $pages("template=code, name=$codeName");
    if(!$code->id) throw new Wire404Exception();

    // do sth with the code page
}

 

  • Like 2

Share this post


Link to post
Share on other sites

... Ooooh. I forgot it.. I'm in Florida (Waiting for the big hurricane uff) ...

but is ok, maybe I don't have other solution than the IDs.. and I don't want to my editors to put the information in another place on the page tree when they should be under codes node...

So, the last shoot.. the scenario is:

Codes (template file)
-- Wall Mount (template without file)
-- Light Commercial (same as above)

Initially Codes render its content (header, body, etc) plus the information of the first child (repeaters with body, pictures, etc)

Codes also have a list of links that was generated from its children name as url segments, to load the same Codes page, but with the content from the new selected child

.. uff seems more easier to see than to explain !

 

EDIT: this post should be before the previous from abdus, I delay in publishing it

Share this post


Link to post
Share on other sites

abdus code would work great, but still i don't understand what is bad about having a template file for each of your children. url segments in those cases have some drawbacks that you may not think of before and always need some extra work (for example creating a sitemap, multilanguage or the like...).

hearing that this scenario makes problems for you i guess maybe your setup is not optimal. using https://processwire.com/docs/tutorials/how-to-structure-your-template-files/page4 this would be very easy.

and using https://processwire.com/blog/posts/processwire-3.0.62-and-more-on-markup-regions/ it would be even easier.

Share this post


Link to post
Share on other sites

Abdus: the problem is that in the parent page I generate the links automatic from the name of the child pages, so the links always match the children names.. even if I add "code--" using the API because when I save the page, and later generate the parent page again the links will include "code--".. the only solution is to use a field other than the name ... ID is the best option because is url friendly..

Abdus: Thanks for your contributions to this forum, you are the best teacher for newbies like me, every post of yours seems a tutorial. It's easier to learn new things in them than with the PW documentation.

Share this post


Link to post
Share on other sites

URLs are generated from page names by default. What I'm trying to show is that you dont have to use IDs for page names, otherwise when generating URLs you'd get /codes/123 instead of /codes/wall-mounted-light. Below is a sample template that should work in your case

<?php namespace ProcessWire;
/** @var Pages $pages */
/** @var Sanitizer $sanitizer */

/** @var Page $child */
$child = null;
if ($input->urlSegment1) {
    $codeChildName = "code--{$input->urlSegment1}";
    $codeChildName = $sanitizer->pageName($codeChildName);

    $child = $pages("parent=$page, name=$codeChildName");
    if (!$child->id) throw new Wire404Exception();
}
?>
<div class="code-page">
    <?php if ($child): ?>
        <!-- RENDER CHILD PAGE -->
        <h1>Child: <?= $child->title ?></h1>
        <?= $child->body ?>
        
    <?php else: ?>
        <!-- RENDER CODE PAGE WITH CHILDREN -->
        <h1><?= $page->title ?></h1>
        <?= $page->body ?>

        <h2>List of children:</h2>
        <ul class="chilren">
        <?php foreach ($page->children as $c): ?>
            <?php $childUrl = "./$c->name"; // generate urls for the child ?>
            <li class="child">
                <a href="<?= $childUrl ?>"><?= $c->title ?></a>
            </li>
        <?php endforeach; ?>
        </ul>
    <?php endif; ?>
</div>

I also concur with @bernhard. If you're modifying the core behavior and rendering child page at the url that matches the child's, then I'd say you should reconsider your approach. You're only complicating it for yourself.

Also, thanks, I'm doing what I can. These questions are like quizzes that I enjoy solving, and get to practice coding with PW.

  • Like 4

Share this post


Link to post
Share on other sites

abdus: This don't works, if we generated the url segment links with:

"./$page->name"

we never found that page with:

$codeChildName = "code--{$input->urlSegment1}"
$pages("name=$codeChildName")

because the page with that name doesn't exist

but looking at your proposal I found one solution:

add a "keyword" to the generated links and then remove that "keyword" after get that url segment.. works perfect!

this at the start of my template file:

<?php namespace ProcessWire; 

$wildcard = "-list";

if($input->urlSegment2) throw new Wire404Exception();

if($input->urlSegment1) {
	$request = $input->urlSegment1;
	}

if($request) {
	$name = str_replace($wildcard,"",$request);
	$name = $sanitizer->pageName($name);
	$codes_page = $pages->get("name=$name");
	if(!$codes_page->id) throw new Wire404Exception();
	} else {
	$codes_page = $page->child("include=all");
	}

?>

then when I generated the links in the template:

<?php foreach($page->children("include=all") as $child) { ?>
	<a href="<?=$child->name.$wildcard?>"><?=$child->title?></a>
<?php } ?>

and that's all.. it's ok? remember that I'm a graphic designer trying to coding

Share this post


Link to post
Share on other sites

I agree with bernhard that this situation is perfect for an ajax solution, but in the parent page I use a javascript plugin that need the markup from the child pages is present in the html output at document ready, not in the dom

Share this post


Link to post
Share on other sites
6 hours ago, Pixrael said:

I agree with bernhard that this situation is perfect for an ajax solution, but in the parent page I use a javascript plugin that need the markup from the child pages is present in the html output at document ready, not in the dom

Never said that ;) I would recommend reading my second link carefully and trying out markup regions :) (... And building your site with a template for your child pages instead of URL segments)

  • Like 1

Share this post


Link to post
Share on other sites
Quote

Your scientists were so preoccupied with whether or not they could, they didn’t stop to think if they should.

I strongly suggest creating a template for the child pages as well. You might not have an issue at the moment, but a month from now, a year from now, when you need to change something, it won't be where you expect it to be. It'll be harder to maintain. I had to do a number of complete rewrites in the past because I was only complicating things for myself for no reason.

  • Like 1

Share this post


Link to post
Share on other sites

I always use the Markup Region since it was included in PW .. thanks for your advice, thanks for everything guys, this community is really like a home with friends

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By louisstephens
      So I have been hard at work creating url segments for a template (api) and everything is working swimmingly in creating a simple end point for svelte.js. I have however, run into a few questions that I can wrap my head around.
      In my api template I have:
      if($input->urlSegment1 === 'clients') { header('Content-Type: application/json'); $clients = $pages->find("template=clients"); $client_array = array(); foreach ($clients as $client) { $id = $client->id; $title = $client->title; $url = $client->url; $clientName = $client->client_name; $clientColor = $client->client_color->value; $assigned = $client->assigned_to->user_full_name; $client_array[] = array( 'id' => $id, 'code' => $title, 'name' => $clientName, 'associated_users' => $assigned, 'url' => $url ); } $client_json = json_encode($client_array, true); echo $client_json; } The output json from this is:
      [ { "id":1644, "code":"abc", "name":"Test Name", "associated_users":null, "url":"\/pw\/clients\/abc\/" }, { "id": 1645, "code": "xyz", "name": "Test Name", "associated_users": null, "url": "\/pw\/clients\/xyz\/" }, ] I was curious is it possible to add in "clients" before this output json so it would appear as 
      clients: [ { "id":1644, "code":"abc", "name":"Test Name", "associated_users":null, "url":"\/pw\/clients\/abc\/" }, { "id": 1645, "code": "xyz", "name": "Test Name", "associated_users": null, "url": "\/pw\/clients\/xyz\/" }, ] I was not really sure of how to tackle this in my php code, and have spent more time than I care to admit trying to figure it out. Another question I have is that "associated_users" is returning null, which in this instance is correct. It is a multi page field that is set to pull a custom name field from the users template, ie "Louis Stephens" would be associated with the first page. I understand that I need to use a foreach to get the correct data, but I was really unsure of how to place this inside an array, or update the array with the new data. Any help with any of this would greatly be appreciated.
    • By Moritz Both
      Greetings!
      For our PW project we use markup regions and, for one template, url segments. The documentation recommends throwing a new Wire404Exception() from the template when the code concludes that the url segments from the request are invalid, and so we do.
      However, the 404 page is not displayed properly. Viewing the page source in the browser we can see that the original, unmodified markup region contents from our _init.php file is prepended to the correct html output, messing the whole page up.
      Any advice is greatly appreciated.
    • By hansv
      Hi everybody
      I want to catch a variable from outside processwire into _main.php
      if(isset($_GET['u']) && $_GET['u'] !== ''){ $gebruikersnaam = $_GET['u']; ... ... This is working fine in a php file in a non processwire environment. 
      In a processwire environment, I get the variable when I refer to /site/templates/_main.php but a great part of my template-code is not shown. 
      From outside processwire I refer to    mydomain/index.php.  If I place   $gebruikersnaam = $_GET['u'];  in index.php, how can I pass through my variable to _main.php?   Or is there an other solution?
      thx
      hansv
    • By louisstephens
      So I have a project coming up soon and one of the goals was to use Google's AMP project for the project's mobile site. I have gone through the tutorials and think I have a good grasp on the matter, but there is still one roadblock I do not really know how to tackle. The site, which uses a responsive grid system, will look great on a mobile and desktop which was is fine by me. However, if a user comes from Google to one of our AMP pages (ie www.example.com/amp) and clicks on a url, they will then be loading our responsive mobile pages and not the amp pages. For the sake of consistency, we really want to "force" users to stay on all the amp pages.
       
      My current thoughts on how to set up this task:
      Allow url segments for all pages using "/amp" Using a simple if statement, load the amp page if it exists <?php if($input->urlSegment1) { // add "&& $input->urlSegment1 == 'amp'" if you've more urlSegments include("partials/amp-page.php"); } else { include("partials/normal.php"); } ?>  
      However, I have hit a roadblock on appending "/amp" to all pages if they came to an amp page via Google, or even if they are on mobile and visit the site. Is this even possible to do, or should we just use the amp pages (if a user comes from google) and allow them to be active on our mobile pages?  We are just trying to give the fastest load times possible, as well as give a consistent look between mobile and desktop versions. As always, I really appreciate the ideas and help.
    • By verdeandrea
      Hello,
      i read that "URL segments only apply if the requested URL did not resolve to an actual page." (from here)
      Is there a way to change this behaviour? 
      I have a parent page loading his children via ajax, and i know which children to load from url segments. So that would be nice to have url segments to have precedence instead of children's url.
      Thanks!
×
×
  • Create New...