devsmo Posted August 13, 2015 Share Posted August 13, 2015 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? Link to comment Share on other sites More sharing options...
Adam Kiss Posted August 13, 2015 Share Posted August 13, 2015 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 More sharing options...
devsmo Posted August 13, 2015 Author Share Posted August 13, 2015 I checked that as well. At least according to the admin panel the page is published, visible and accessible by guest. Link to comment Share on other sites More sharing options...
LostKobrakai Posted August 13, 2015 Share Posted August 13, 2015 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 More sharing options...
devsmo Posted August 13, 2015 Author Share Posted August 13, 2015 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 More sharing options...
LostKobrakai Posted August 13, 2015 Share Posted August 13, 2015 Could you try if moving those pages in the page tree and setting them back in place does change the behavior? Are those pages created via the api / backend / copied? Link to comment Share on other sites More sharing options...
Adam Kiss Posted August 13, 2015 Share Posted August 13, 2015 And one more thing: Is this multi language? (Then, the 'child' could not be active). Link to comment Share on other sites More sharing options...
devsmo Posted August 14, 2015 Author Share Posted August 14, 2015 - 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 More sharing options...
LostKobrakai Posted August 14, 2015 Share Posted August 14, 2015 Are you maybe replacing the find() method somewhere? $pages->find() does always return a PageArray and never null. Link to comment Share on other sites More sharing options...
devsmo Posted August 14, 2015 Author Share Posted August 14, 2015 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 0protected 'numLimit' => int 0protected 'numStart' => int 0protected '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 More sharing options...
devsmo Posted August 17, 2015 Author Share Posted August 17, 2015 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 More sharing options...
LostKobrakai Posted August 17, 2015 Share Posted August 17, 2015 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 More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now