Jump to content

Check if a given page has children


benjaminE
 Share

Recommended Posts

Hello,

I'm trying to write an if statement which queries whether a given page - identified by that page's title - has any children.

I've tried various things, the most hopeful being:

$info = $pages->find("title=previous caption winners")->children;
            
if ( $info >= 1 ) {
     //do stuff       
};

but to no avail.

This seems like a fairly simple task but I've had no success despite my efforts to find answers here and elsewhere.

Any help would be greatly appreciated.

All thanks,

ben

Link to comment
Share on other sites

What you've got as a result is a PageArray so you'd need to check the count like this (edit: ..and change find to get as diogo says below):

if(count($info) >= 1) {

// do stuff

}

If there are potentially lots of children, it would be better to do it for example like this:
$childCount = $pages->count("parent.title=previous caption winners");

if($childCount >= 1) {

// do stuff

}

This way you wont end up fetching all the children just to count them. :)
  • Like 3
Link to comment
Share on other sites

The find() method returns an array of pages, and you can on only check for children in a individual page. If your goal with this selector is to get only one page, use get() instead.

$info = $pages->get("title=previous caption winners")->children;

But, if all you want is to check if there are children, the shortest method would be:

if ($pages->get("title=previous caption winners")->child->id)

It gets the first child and checks for it's id

edit: nik was faster :)

  • Like 4
Link to comment
Share on other sites

Thank you both for your prompt and good replies.

I've gone with Diogo's second option and it's worked perfectly, thank you.

Nik: I like the elegance of your second solution but I can't seem to get it to work. I tested the output of:

$childCount = $pages->count("parent.title=previous caption winners");

But it came out with "0" despite the fact that there are 2 children of that parent. When I switched the parent title to another with 4 children, it outputted "1". I've no idea why this might be happening...

Thanks again to both of you though.

Link to comment
Share on other sites

@diogo: Faster yes, but I ignored that get/find-issue and gave a solution that didn't work for benjaminE :P.

@benjaminE: That's weird as that very same thing does seem to work for me. Support for parent subfields in selectors was added somewhere between version 2.2.10 and 2.2.12 - are you using something newer? Though I don't really think that's the reason as that syntax would have given a straight error before the implementation was in place, I guess.

Diogo already gave you a perfectly working solution with no performance issues so I'm asking just to understand what could have caused those results you described. One reason could have been hidden/unpublished child pages, but diogo's solution handles those the same way (leaving them out). It must be something else then.

Link to comment
Share on other sites

@nik: I'm using ProcessWire 2.3.0...

One issue here might be that the parent page is set to "Hidden" and uses a template with no corresponding template file (I don't want the children to be accessible through their own pages).

However, this wouldn't explain why plugging in the parent with 4 children outputs only "1"; both the parent and the children here are not hidden and have templates with corresponding files.

I'm afraid my ProcessWire skills are not good enough to probe deeper into diagnostics but I'd be happy to answer any more questions if they'd help find a solution... Perhaps useful as your proposed method might come in handy for other applications that require more subtlety than just checking if any number of children exist.

Link to comment
Share on other sites

If the parent page is hidden you'd have to include "include=hidden" in the selector when doing a find(), but not if you get() the page explicitly.

Also wanted to note that doing 

$pages->get("title=previous caption winners")->children;

isn't a very reliable method to find a page by it's title, since the title isn't unique. In most cases it makes more sense to use id or page name, page path.

$pages->get(1005)->children;

Or maybe

$pages->get("/some/path/")->children;

To find if a parent has children there's also a method in PW numChildren().

if($pages->get(1004)->numChildren) {
    // has children
}

In PW 2.3 there's a new version of numChildren() to make it access aware if you pass true as the argmument

if($pages->get(1004)->numChildren(true)) {
    // has children that are really visible to the user
}
  • Like 7
Link to comment
Share on other sites

  • 1 month later...
if($pages->get(1)->numChildren(true)) {
    // has children that are really visible to the user
}

output = 10 [total with 'hidden' pages]

echo count($pages->get(1)->children); // output 5, should be 4
echo count($pages->get(1026)->children); // output 3, correct

1 is the root, AFAIK, and I have four subpages, although the number returned is '5'  :huh:

For all other pages that seems to work however...  Not sure if I'm missing something, not so important for me ATM, just wanted to mention it...

Link to comment
Share on other sites

1 is the root, AFAIK, and I have four subpages, although the number returned is '5'

You can tell what the unexpected page is by outputting the contents of children() rather than just outputting the count.

foreach($pages->get(1)->children) as $n => $child) 
  echo "<p>$n. $child->url</p>";
  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...