Jump to content

Unexpected behavior for $page->find() method


devsmo
 Share

Recommended Posts

Hello,

Recently I ran into some weird behavior with the find() method, when using it within the context of a single $page.

Although this is easy (and perhaps more correct) to work around using the get(), child() or children() methods, I'd still like to understand what is happening here.

This is an example of a piece of code, where $page is trying to get its child with a specific template, using the find() method, but returns nothing instead.



<?php

// Prepare PW
$_SERVER['SERVER_NAME'] = 'localhost';
$_SERVER['HTTP_HOST'] = 'localhost';
$_SERVER['REQUEST_URI'] = '/index.php';

// get Wire'd
require_once dirname(__FILE__).'/../../www_composer/index.php';

// get some entries where the template failed to laod
$data = file_get_contents('failed_entries.json');
$data = json_decode($data);

foreach ( $data as $row )
{
$entry = wire('pages')->get('template=offers-page, email='. $row->email);

echo sprintf("This page has the id %d, it contains meta-data for an email\n", $entry->id);
echo sprintf("\t- it has %d child (with ID %d), which is a template ('email-base'),\n",
$entry->numChildren(),
$entry->child()->id
);
echo sprintf("\t- the child (template) has %d children (which are blocks in the template),\n", $entry->child()->numChildren());
echo "We want to get the child that uses the 'email-base' template (because in theory there could be many children to this page)\n";
echo sprintf(
"\tWhy is find() returning '%s' when filtering with template name,\n",
($entry->find('template=email-base')->count()? $entry->find('template=email-base')->count(): 'NOTHING')
);
echo sprintf(
"\twhile get() returns the expected page with id: %d\n",
$entry->get('template=email-base')->id
);
echo "When further researching this, it would seem that using find on \$page, actually returns it\'s grandchildren\n";
$i=1;
foreach ( $entry->find() as $gc ) {
echo sprintf("\t- I'm a grandchild, and my parent is %d and not %d\n",
$gc->parent()->id,
$entry->id
);
$i++;
}

break;// casue we only need to look at one..
}


Even more interesting is that sometimes this $page->find('template=tpl-name')->first()->id returned an id, and sometimes it threw a notice.

The above code is a test CLI script, which produces weird results.

On the other hand when I tested using find() in a template, it worked while testing, but later our users reported an error that is caused by $page->find('template=tpl-name')->first()->id throwing a notice.

What is the behavior of find() supposed to be in this case? 

Am I missing something?

post-2624-0-67739700-1439471998_thumb.pn

Link to comment
Share on other sites

My guess: the child is hidden. $page->find() finds all descendants from the $page. If logged in as a  superuser, you see any page on the site. If logged in as a guest, the pages set to hidden (and/or other settings you have on the page) ar invisible. find() finds 6 pages — child + 5 grandchildren, but child is hidden for guest, thus returning only the 5 grandchildren.

Link to comment
Share on other sites

The difference between find and get is in this case the different selectors that get build:

$entry->find() -> $pages->find("has_parent=$entry->id");
$entry->get() -> $pages->find("parent_id=$entry->id");

If you'd supply a selector, it will be added to the one shown above. If you still find an issue with these, then Ryan needs to check the PageFinder. 

One useful info: Which version of PW are you using? There where issues with the table holding information about page parents when copying pages.

Link to comment
Share on other sites

The version is 2.5.3

I tested with

$pages->find("has_parent=$entry->id");

and

$pages->find("parent_id=$entry->id");

The later returned the template page as expected, and the first query returned the 5 grandchildren

Link to comment
Share on other sites

- This project isn't multi-language.

- The pages are created through the api.

When I moved all the grandchildren down one level, so that $page only has children and no grandchildren: $pages->find("has_parent=$entry->id") returned empty.

I also tested this in a template, while being logged in as admin



var_dump( $page->children('template=email-base')->first()->id );
var_dump( $page->get('template=email-base')->id );
var_dump( $page->child()->id );
var_dump( $page->find('template=email-base')->first()->id );


The 3 first ones return the page id.

The last one throws an error (since first() isn't a method of null).

Link to comment
Share on other sites

It actually returns an empty PageArray.

And the error (notice), is probably about the '->id' 

EDIT, Here's a bit of the var_dump for $page->find('template=email-base'):

---

object(PageArray)[297]
protected 'numTotal' => int 0
protected 'numLimit' => int 0
protected 'numStart' => int 0
protected 'selectors' =>
object(Selectors)[292]
protected 'selectorStr' => string 'has_parent=1754, template=email-base' (length=48)
protected 'quotes' =>
array (size=5)
'"' => string '"' (length=1)
''' => string ''' (length=1)
'[' => string ']' (length=1)
'{' => string '}' (length=1)
'(' => string ')' (length=1)

..

---

Link to comment
Share on other sites

I spent some time dumping and analyzing the SQL queries that PW does when doing the find.

It seems that find() works fine. Instead the issue appears when we save pages via the API.

The page that cannot be found with find is missing entries in the pages_parents table,

The first query is a broken page, and the second one is a sibling which works as expected.

mysql> SELECT * FROM pages_parents WHERE pages_id=1754;
Empty set (0.00 sec)

mysql> SELECT * FROM pages_parents WHERE pages_id=1407;
+----------+------------+
| pages_id | parents_id |
+----------+------------+
|     1407 |          1 |
|     1407 |       1172 |
|     1407 |       1193 |
+----------+------------+
3 rows in set (0.00 sec)

I'll post a conclusion here if I ever manage to duplicate this issue consistently.

Link to comment
Share on other sites

That's exactly the issue I wanted to check on by lettings you move these pages, as this should trigger an update to the parents table. Maybe you should open an issue over at github about this and include how you're saving those pages, which fail to have parents assigned.

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...