Support » Fixing WordPress » More fun with sub sub pages

  • I’ve been reading around a lot of the discussion following sub pages and sub-sub pages, but I haven’t quite found the answer I’m looking for (most of the posts seem to concern wp_list_pages showing a proper nav list when on page, child, or sub-child…)

    I think I know roughly how you would do this in plain English, but my PHP isn’t that strong.

    Problem

    I need to define a variable for templating reasons that if you are on a page, any of its sub-pages, or any of those sub-page’s sub-pages.. and so on.

    Following the codec example I have thus far got:

    <?php
    
    if 	(is_page('20') || $post->post_parent=="20") {
    	$sidebar_call = 1;
    } elseif (is_page('34') || $post->post_parent=="34") {
    	$sidebar_call = 2;
    } elseif (is_page('11') || $post->post_parent=="11") {
    	$sidebar_call = 3;
    } elseif (is_page('12') || $post->post_parent=="12") {
    	$sidebar_call = 4;
    } else {
    	$sidebar_call = "default";
    }	
    
    ?>

    As I expected, this works fine on any of the above pages or their sub-pages, but when you get to a sub-sub-page the variable is assigned the default value.

    I can imagine that I need to create an array (as can now be done in 2.5), but am not sure how to go about it.

    I know there is a function for get_children, but I haven’t found any documentation on how that works (and whether it gets children of the children!).

    My English version of the code would be:

    <?php
    
    if 	(is_page('20') || (is_page(get an array of all children and sub children of page 20...) {
    	$sidebar_call = 1;
    } elseif (is_page('34') || (is_page(get an array of all children and sub children of page 34...) {
    	$sidebar_call = 2;
    } etc...
    
    ?>

    However I’m not sure exactly how to make this happen….

    Any ideas?

Viewing 15 replies - 1 through 15 (of 34 total)
  • you’re sort of doing this the wrong way around I think.

    what you want to do is to keep checking the parent page until you reach the top level, and do something if you find the correct top-level ID right?

    $parentid = $post->post_parent;
    while ($parentid) {
      $page = get_page($parentid);
      $parentid = $page->post_parent;
      if ($parentid=="2") echo 'this is a child of the About page';
      if ($parentid=="483") echo 'this is a child of a test page';
    }

    the while loop ends when there are no more parents. if your ID is found along the way, then the output is echoed.

    Thread Starter alexleonard

    (@alexleonard)

    Hey Ivovic,

    Thanks for your speedy response. I think I can understand what you’re doing here.

    Basically, you first get the parent id of the post and assign it to $parentid (not sure what happens if the post doesn’t have a parent?)

    and then I start to find it hard to explain in plain english πŸ™‚ basically you’re working out that if that parent has another parent it will assign that to parentid and loop back to see if it finds another one, and then once that loop is completed you run some if statements and whichever one it matches it executes..

    (I’m learning PHP slowly, so this is the brain process I have to go through πŸ˜‰

    Anyway, I took what you had in there and I didn’t have any joy with it (none of my if statements are evaluating as TRUE evidently..). I just tried to output a basic statement

    $parentid = $post->post_parent;
    while ($parentid) {
      $page = get_page($parentid);
      $parentid = $page->post_parent;
      if ($parentid=="20") echo "<p>CLC Page/sub page</p>";
      if ($parentid=="34") echo "<p>Community Link Page/sub page</p>";
      if ($parentid=="11") echo "<p>Recycle Scotland Page/sub page</p>";
      if ($parentid=="12") echo "<p>Stepping Stones Page/sub page</p>";
      if ($parentid=="2") echo "<p>Home Page or sub page</p>";
    }

    I tried running this through some else/if type of layout as well (just to see if I could return a default result) and nothing was going on there either.

    However I’m probably missing something πŸ˜‰

    Thread Starter alexleonard

    (@alexleonard)

    Oh, unfortunately I don’t have a URL to provide as an example as this is being developed offline πŸ™

    Still, it’s a project for the Edinburgh University Settlement, which is charity organisation in Scotland which aims to provide “Effective and lasting social & community development”, just so the Community Link etc makes sense.

    (not sure what happens if the post doesn’t have a parent?)

    if it doesn’t, then the variable is empty, and the while loop is essentially skipped.

    I posted that on the fly without thinking too much about it, so let me make a slight correction, which I’ll then explain in plain english.

    $parentid = $post->post_parent;
    while ($parentid) {
      if ($parentid==2) echo 'this is a child of the About page';
      if ($parentid==483) echo 'this is a child of a test page';
      $page = get_page($parentid);
      $parentid = $page->post_parent;
    }

    I just swapped the order, because what I originally posted wouldn’t have caught the immediate parent… only the grandparent (oops).

    Here it is in plain english:

    lets see if the page we're on has a parent.
    if it does, and while we have parents to keep checking...
       Have we found an ID we like? If so, do this. If not, do nothing.
       ...
       lets pull the parent page so we can see what its parent is
       lets grab the ID of that grandparent now, so we can check it
    keep looping

    The loop stops when the last line inside the loop, sets $parentid to an empty value. No parents = no loop.

    the reason you’re probably not getting any joy is because I screwed up the order of if-statements, and you didn’t have enough sub-subs to test with.

    also, this needs to be in page.php, or a suitable page template, but I’m asuming you’ve got that covered already. If by chance you’re using this in your functions.php, you’ll have to modify it to pull the initial value (but you’re not, right?)

    my original code also only checks parents / grandparents / great grandparent, not the page you’re on now… to do that, you’d need something like this:

    if (is_page(2)) echo 'this is About';
    elseif (is_page(483)) echo 'this is Test';
    else {
      $parentid = $post->post_parent;
      while ($parentid) {
        if ($parentid==2) echo 'this is a child of the About page';
        if ($parentid==483) echo 'this is a child of a test page';
        $page = get_page($parentid);
        $parentid = $page->post_parent;
      }
    }

    this will continue to do absolutely nothing unless one of the IDs are matched (that is, it will just fail silently without a default result).

    Please keep in mind, I haven’t tested any of this since I have my hands a little full right now, but I *think* it’ll work… barring any typos or brain farts.

    Thread Starter alexleonard

    (@alexleonard)

    Ivovic,

    You’re a legend. I’m going to go through that piece by piece and dissect it all.

    I’m actually going to look to turn this into a function returning a variable so that I can use this work to assign not just different sidebars to different “Projects” in the website, but also so that I can assign an extra class to the body of the page dependent on which section of the site you’re in. This will allow me to vary the colours etc with some simple cascades of style!

    I’ll report back when I have things worked out and hopefully the end function can be of use to someone else some day.

    (I’ve just started learning PHP properly – I’ve just covered the basics of functions so am eager to test it out, although I’ll get it working in our initial test scenario before I go messing with functions…!)

    Thanks again, really appreciate the excellent explanations when you’re so busy.

    Moderator Samuel Wood (Otto)

    (@otto42)

    WordPress.org Admin

    There’s actually a function to do this sort of thing, but it’s broken.
    See here: http://trac.wordpress.org/ticket/7029

    If it worked, it would look sorta like this:

    $ancestors = get_post_ancestors($post);
    if (in_array(2,$ancestors)) echo "2 is an ancestor";
    if (in_array(array(2,483),$ancestors)) echo "2 or 483 is an ancestor";

    Happy to help, Alex… I’ll be glad to hear back when you’ve had a chance to make this work.

    given that you’ll be reusing this, making it into a function is definitely a good idea, just be sure to pass the current page ID to the function you make, as the $post variable isn’t available to functions in functions.php by default.

    The rest of the code works anywhere, you just need to give the function a starting point.

    Good luck with it.

    edit: Otto, I’d looked into that (when making my breadcrumbs bit)… but as you say… it no worky.

    Thread Starter alexleonard

    (@alexleonard)

    Hey guys,

    I got it working (not in a function yet, about to do that).

    Ivovic, I found that the last example you gave worked on a sub sub page, but not on a master page – so I figured that maybe if the page doesn’t have a page_parent then it doesn’t return a result (I couldn’t find out whether it returns NULL if it is a parent).

    So I ran a conditional first and if the page isn’t a sub page than parentid is just assigned the ID and it looks like it’s working.

    if (is_page() && $post->post_parent ) {
      $parentid = $post->post_parent;
    } else {
      $parentid = $post->ID;
    }
    
    while ($parentid) {
      if ($parentid==20) echo 'Page 20, or a child/subchild of 20
    ';
      if ($parentid==34) echo 'Page 34, or a child/subchild of 34
    ';
      if ($parentid==11) echo 'Page 11, or a child/subchild of 11
    ';
      $page = get_post($parentid);
      $parentid = $page->post_parent;
    }

    I’m going to look at converting this into a function now (and thanks for the reminder of passing data (I better remember to return it too! Ah the joy of finally learning about this stuff – a lot less blind stabbing in the dark!).

    Thanks again.

    Alex

    Edit: ps. it of course goes without saying that if I’m doing something a weird way, please feel free to correct me πŸ™‚

    yeah, I thought about setting $parentid to the current page ID, but since the loop is structured not to break on its own, that’s a little inefficient because it tries to pull the parent page of the top-level page even if it finds a match.

    there’s going to be a cleaner way to to this, but as you’ve noticed from my mistakes and distractions, my head’s not really in it very solidly right now.

    either way, it’s probably not a bad idea to open up some curlies after those if-statements and insert a break.

    if ($parentid==2) {
      echo 'do stuff';
      break;
    }

    that’ll stop the cycle once a match is found… but I hate using breaks, ‘cos there’s usually a far nicer way to handle the trickledown.

    edit: I want to note though… there’s nothing wrong with getting something in there that works for now, then refining this while taking a break from your layout/graphics work… no doubt your requirements will evolve somewhat as your design takes shape anyway.

    Thread Starter alexleonard

    (@alexleonard)

    More fun and games πŸ™‚

    I will actually probably look at just getting this working right now (so I can send the project heads an example of the site) but I’ll definitely be looking to refine it. First up so that something the eventual admins do won’t break it, but also, if I can work out a useful function that could prove it’s worth again and again, then I’d be very happy.

    So I found that my above example was working very well, until I went to my overall news page. As I’m using a static front page, I’ve assigned my posts page to “News”(ID=3).

    However my tests showed that the code was returning the value of the most recent post, rather than that overall page id.

    So I’ve (probably very unsightly) got this working using:

    if (is_page() && $post->post_parent ) {
    	$parentid = $post->post_parent;
    } else {
    	$parentid = $post->ID;
    }
    
    while ($parentid) {
     echo '<li class="widget">Parentid = '.$parentid.'</li>';
     if ($parentid==20) dynamic_sidebar('CLC');
     if ($parentid==34) dynamic_sidebar('Community Link');
     if ($parentid==11) dynamic_sidebar('Recycle Scotland');
     if ($parentid==12) dynamic_sidebar('Stepping Stones');
     $page = get_post($parentid);
     $parentid = $page->post_parent;
     if (!$parentid==(20 || 34 || 11 || 12)) dynamic_sidebar('Default');
    }

    I’m going to grab some dinner and come back to this.

    Thanks again!

    I’m pretty sure that’ll call the sidebar numerous times on sub-sub pages which don’t match those IDs…

    bad mojo.

    I think the best way to do what you want is to set a flag.

    [edited in lieu of the following]

    neatening:

    $sidebar = 'Default';
    while ($parentid) {
     echo '<li class="widget">Parentid = '.$parentid.'</li>';
     if ($parentid==20) $sidebar = 'CLC';
     if ($parentid==34) $sidebar = 'Community Link';
     if ($parentid==11) $sidebar = 'Recycle Scotland';
     if ($parentid==12) $sidebar = 'Stepping Stones';
     $page = get_post($parentid);
     $parentid = $page->post_parent;
    }
    dynamic_sidebar($sidebar);

    eventually when you functionize this, this should end up in your template:

    dynamic_sidebar(eval_sidebar($pageid));

    with eval_sidebar being your new function, which returns the name of the sidebar, given a page ID.

    Thread Starter alexleonard

    (@alexleonard)

    Ivovic, another brilliant point there.

    It never occurred to me to just declare a default $sidebar value πŸ™‚

    So, it’s all working and I’ve turned it into a function successfully (although I’m not sure how tidy it is πŸ˜‰ – I’m not sure I would have gotten there without you, and I’m starting to understand more and more.

    In my header I can now assign a class to the body with:

    <body class="
    <?php echo eval_page($post->ID);?>
    ">

    and in my footer I can call different sidebars with:

    <ul>
    <?php dynamic_sidebar(eval_page($post->ID)); ?>
    </ul>

    And here’s my eval_page function:

    function eval_page($pageid) {
     $pageval = get_post($pageid);  // variable assignment unnecessary?
     if (is_page() && $pageval->post_parent ) {
      $parentid = $pageval->post_parent;
      } else {
        $parentid = $pageval->ID;
        }
     $eus_page = "Default"; // Set the page type as default
    
     while ($parentid) {
      if ($parentid==20) $eus_page = 'CLC';
      if ($parentid==34) $eus_page = 'Community Link';
      if ($parentid==11) $eus_page = 'Recycle Scotland';
      if ($parentid==12) $eus_page = 'Stepping Stones';
      $page = get_post($parentid);
      $parentid = $page->post_parent;
     }
    
     return $eus_page;
    
    }

    It all works (which partially amazes me) and I’m thrilled. As per usually if there’s a neater way to do it, then please feel free to dissect!

    Of course, there’s a couple of considerations..

    1. If the website ever has a ‘new’ section added, then the function will have to be adjusted.
    2. I’ve just realised that each of this organisation’s “Projects” might require a “News” page of their own – so I’ve got to add parameters for single.php so that if in_category… then return the right $eus_page so that people aren’t having sidebars changing randomly on them!

    Again, many thanks for all the advice πŸ™‚

    As far as I can see, in order to keep your sidebar names in one spot only, you have to pull $pageval up the top there.

    So, no it *is* necessary with the code you have… but let’s see… I don’t really think you need that top section, and now that I’ve had a coffee I’m prepared to say it πŸ˜›

    does this still work?

    function eval_page($pageid) {
     $eus_page = "Default"; // Set the page type as default
     while ($pageid) {
      if ($pageid==20) $eus_page = 'CLC';
      if ($pageid==34) $eus_page = 'Community Link';
      if ($pageid==11) $eus_page = 'Recycle Scotland';
      if ($pageid==12) $eus_page = 'Stepping Stones';
      $page = get_post($pageid);
      $parentid = $page->post_parent;
     }
     return $eus_page;
    }

    see how you were filling that ‘necessary’ variable? now it just happens a bit later in the while loop unless the match is found before that even happens.

    The only other issue I can see is that your body class names now have spaces in them, which I don’t think is ideal. That’s easily fixed though.

    You’re welcome by the way, it’s been fun trying to code and juggle other stuff at the same time – I don’t do it very often, so I’m glad its YOU dealing with the fallout πŸ˜‰

    Thread Starter alexleonard

    (@alexleonard)

    I can’t believe I forgot about the class names with spaces being a problem!

    I was so focussed on getting the value returned that I didn’t care what it was πŸ™‚

    I’m going to test this out now.

Viewing 15 replies - 1 through 15 (of 34 total)
  • The topic ‘More fun with sub sub pages’ is closed to new replies.