a-ok Posted June 20, 2016 Share Posted June 20, 2016 I know you can use getForPage(); to get the page that a repeater is being used on, but can you do the same within the find selector? Without having to loop? $pages->find('template=repeater_collections_detail_images, include=hidden, sort=name'); Something like... $pages->find('template=repeater_collections_detail_images, getforpage=collections_detail_designer=123 ,include=hidden, sort=name'); What this would do is find all the repeaters that's page it is on has the collections_detail_designer of 123. I was thinking you could just search all pages that has collections_detail_designer=123 then return all those repeaters I don't think that's possible? Link to comment Share on other sites More sharing options...
Tom. Posted June 20, 2016 Share Posted June 20, 2016 Can't you just do a selector for the field? $pages->find("repeater.count>0") Link to comment Share on other sites More sharing options...
a-ok Posted June 24, 2016 Author Share Posted June 24, 2016 On 6/20/2016 at 11:42 PM, Tom. said: Can't you just do a selector for the field? $pages->find("repeater.count>0") It's within a filtering selector, for example: <?php $selector = "template=repeater_collections_detail_images, include=all, status!=unpublished, sort=collections_detail_image_page_title, sort=collections_detail_image_colour"; if ($types != "all") $selector .= ", collections_detail_type=$types"; if ($colours != "all") $selector .= ", collections_detail_image_colour.collections_colours_group=$colours"; if ($patterns != "all") $selector .= ", collections_detail_pattern=$patterns"; if ($designers != "all") $selector .= ", collections_detail_designer=$designers"; ?> I'm searching repeaters but they need to reference back to the page they are on; the types, patterns and designers are pageFields on the page they are included on, not within the repeater. Link to comment Share on other sites More sharing options...
a-ok Posted June 24, 2016 Author Share Posted June 24, 2016 Any thoughts @ryan? Link to comment Share on other sites More sharing options...
Robin S Posted June 24, 2016 Share Posted June 24, 2016 Maybe I'm not understanding you right, but can't you search for pages that contain the repeater fields and then get the repeater items for those pages? I think (based on the code you showed in this thread) that the fields you are filtering and sorting on are fields in the get-for page rather than fields that are necessarily inside the repeater items so it seems like what you want to be finding are the get-for pages. Another general idea that might be useful: if you look at the page structure around repeaters in the Admin section of the tree you see that the repeaters parent name is "for-page-1234" where 1234 is the id of the page the repeater is on. So if you want to search for repeater items directly with a $pages->find() you could first construct an array of parent page names to use in the selector. Something like: <?php $get_for_ids = $pages->find("foo=bar")->each("id"); $parent_names = array_map( function($item) {return "for-page-$item";}, $get_for_ids ); $parent_names = implode('|', $parent_names); $repeater_items = $pages->find("template=repeater_my_repeater, parent.name=$parent_names"); 2 Link to comment Share on other sites More sharing options...
a-ok Posted June 25, 2016 Author Share Posted June 25, 2016 Thanks so much for the help, again (!!!), @Robin S. Quote Maybe I'm not understanding you right, but can't you search for pages that contain the repeater fields and then get the repeater items for those pages? Maybe I'm not understanding, either. Basically, I have a filtering/tagging system set up, which upon selecting specific tags and hitting 'Submit' it'll return the repeaters with those tags etc. <form class="collections-filter" action="<?php echo $pages->get('template=collections-results')->url; ?>" method="get"> Then on the 'collections-results' template I have something like the code below. <?php $types = $input->get->type; ?> <?php $colours = $input->get->colour; ?> <?php $patterns = $input->get->pattern; ?> <?php $designers = $input->get->designer; ?> <?php $selector = "template=repeater_collections_detail_images, include=all, status!=unpublished, sort=collections_detail_image_page_title, sort=collections_detail_image_colour"; if ($types != "all") $selector .= ", collections_detail_type=$types"; if ($colours != "all") $selector .= ", collections_detail_image_colour.collections_colours_group=$colours"; if ($patterns != "all") $selector .= ", collections_detail_pattern=$patterns"; if ($designers != "all") $selector .= ", collections_detail_designer=$designers"; ?> <?php $results = $pages->find($selector); ?> <?php include('./collections-filters.inc'); ?> <?php if (count($results)) : ?> <div class="container-fluid"> <div class="row"> <div class="fabric-list-container collections-results all"> <?php foreach ($results as $fabric) : ?> <?php include('./fabrics-list.inc'); ?> <?php endforeach; ?> </div> </div> </div> <?php endif; ?> I don't think you can return pages with those repeater fields as one selector without looping? I could use $pages->find("collections_detail_images.count>0") but that'll only return the pages and not the repeaters themselves... I need to return each repeater. The issue with returning each repeater, however, is that I need to check, in the selector, the page the repeater is on and not just the repeater itself which seems to be impossible to do in one selector. For example, what would be ideal is: <?php $selector = "template=repeater_collections_detail_images, include=all, status!=unpublished, sort=collections_detail_image_page_title, sort=collections_detail_image_colour"; if ($types != "all") $selector .= ", getForPage.collections_detail_type=$types"; // This needs to look at the page the repeater is on if ($colours != "all") $selector .= ", collections_detail_image_colour.collections_colours_group=$colours"; if ($patterns != "all") $selector .= ", getForPage.collections_detail_pattern=$patterns"; // This needs to look at the page the repeater is on if ($designers != "all") $selector .= ", getForPage.collections_detail_designer=$designers"; // This needs to look at the page the repeater is on ?> Link to comment Share on other sites More sharing options...
a-ok Posted June 25, 2016 Author Share Posted June 25, 2016 11 hours ago, Robin S said: So if you want to search for repeater items directly with a $pages->find() you could first construct an array of parent page names to use in the selector. Something like: <?php $get_for_ids = $pages->find("foo=bar")->each("id"); $parent_names = array_map( function($item) {return "for-page-$item";}, $get_for_ids ); $parent_names = implode('|', $parent_names); $repeater_items = $pages->find("template=repeater_my_repeater, parent.name=$parent_names"); This could be super useful, actually. I'm thinking I could use this then then apply it to the filter selector... Link to comment Share on other sites More sharing options...
Robin S Posted June 25, 2016 Share Posted June 25, 2016 Here is another way you can get your repeater items, by first finding the pages those repeaters are on. Not tested. <?php // sanitized input $types = $sanitizer->selectorValue($input->get->type); $patterns = $sanitizer->selectorValue($input->get->pattern); $designers = $sanitizer->selectorValue($input->get->designer); $colours = $sanitizer->selectorValue($input->get->colour); // selector $selector = "template=template_with_repeater_field, collections_detail_images.count>0, sort=title"; if ($types != "all") $selector .= ", collections_detail_type=$types"; if ($patterns != "all") $selector .= ", collections_detail_pattern=$patterns"; if ($designers != "all") $selector .= ", collections_detail_designer=$designers"; // here we make sure we only find pages that have the right colour in one of their repeater items if ($colours != "all") $selector .= ", collections_detail_images=[collections_detail_image_colour.collections_colours_group=$colours]"; $results = $pages->find($selector); include './collections-filters.inc'; // not sure what this does ?> <?php if(count($results)): ?> <div class="container-fluid"> <div class="row"> <div class="fabric-list-container collections-results all"> <?php foreach($results as $result) { $fabrics = $result->collections_detail_images; $fabrics->sort("collections_detail_image_colour"); if($colours != "all") { $fabrics->filter("collections_detail_image_colour.collections_colours_group=$colours"); } foreach($fabrics as $fabric) { include './fabrics-list.inc'; } } ?> </div> </div> </div> <?php endif; ?> Another thought: seeing as you want to do all this stuff with your repeater items outside the context of them being fields in another page maybe repeaters are not the ideal mechanism for your data. Could these repeater items instead be normal pages, related to their 'get-for' pages either via a parent-child relationship or via a Page field in the collections_detail_images pages? You can make the collections_detail_images pages easy to add by including them in the "Add New" menus. 1 Link to comment Share on other sites More sharing options...
LostKobrakai Posted June 26, 2016 Share Posted June 26, 2016 For this to work in a single selector you'd need a db connection from the repeater page to the holder, but you've only the field on the repeater "holder", which is the wrong direction. With an pagefield or a real parent/child relation you could use subselectors: parent.id=[myParentsField=MustBe, this=or|that], INeed=toBeThis, and=that You could only go this way: $holders = $pages->find("myParentsField=MustBe, this=or|that"); $validRepeaters = new PageArray(); $holders->each(function($holder) use($validRepeaters) { $validRepeaters->import($holder->myRepeaterField->find("INeed=toBeThis, and=that")); }); This is kinda similar to this one, but not exactly as pages could be selected in multiple pagefields, whereas repeaters are (without api usage) single selection only: https://processwire.com/talk/topic/9730-get-pages-used-by-a-pagefield/ Link to comment Share on other sites More sharing options...
a-ok Posted June 27, 2016 Author Share Posted June 27, 2016 On 6/26/2016 at 0:04 AM, Robin S said: Here is another way you can get your repeater items, by first finding the pages those repeaters are on. Not tested. <?php // sanitized input $types = $sanitizer->selectorValue($input->get->type); $patterns = $sanitizer->selectorValue($input->get->pattern); $designers = $sanitizer->selectorValue($input->get->designer); $colours = $sanitizer->selectorValue($input->get->colour); // selector $selector = "template=template_with_repeater_field, collections_detail_images.count>0, sort=title"; if ($types != "all") $selector .= ", collections_detail_type=$types"; if ($patterns != "all") $selector .= ", collections_detail_pattern=$patterns"; if ($designers != "all") $selector .= ", collections_detail_designer=$designers"; // here we make sure we only find pages that have the right colour in one of their repeater items if ($colours != "all") $selector .= ", collections_detail_images=[collections_detail_image_colour.collections_colours_group=$colours]"; $results = $pages->find($selector); include './collections-filters.inc'; // not sure what this does ?> <?php if(count($results)): ?> <div class="container-fluid"> <div class="row"> <div class="fabric-list-container collections-results all"> <?php foreach($results as $result) { $fabrics = $result->collections_detail_images; $fabrics->sort("collections_detail_image_colour"); if($colours != "all") { $fabrics->filter("collections_detail_image_colour.collections_colours_group=$colours"); } foreach($fabrics as $fabric) { include './fabrics-list.inc'; } } ?> </div> </div> </div> <?php endif; ?> Another thought: seeing as you want to do all this stuff with your repeater items outside the context of them being fields in another page maybe repeaters are not the ideal mechanism for your data. Could these repeater items instead be normal pages, related to their 'get-for' pages either via a parent-child relationship or via a Page field in the collections_detail_images pages? You can make the collections_detail_images pages easy to add by including them in the "Add New" menus. Thanks for your help, again, Robin. I see what you're doing... instead of querying the repeaters and trying to get three sets of data (type, designer and pattern) from the page they are on, you're getting all the pages then getting getting the repeater field (colour) required. The idea of using the filter after the first query is lovely. I'm wondering if you can explain what the square brackets do in the top query? if ($colours != "all") $selector .= ", collections_detail_images=[collections_detail_image_colour.collections_colours_group=$colours]"; This is where it may be going wrong (currently if I filter by 'Blue', for example, it's still returning all the colours). Link to comment Share on other sites More sharing options...
a-ok Posted June 27, 2016 Author Share Posted June 27, 2016 Upon double checking one of the collections, it's returning a page where the colour filtered isn't part of the repeater. // here we make sure we only find pages that have the right colour in one of their repeater items if ($colours != "all") $selector .= ", collections_detail_images=[collections_detail_image_colour.collections_colours_group=$colours]"; There must be something going wrong here. I can't work out why... it's returning all the pages then when it gets to colour, it should be looking at the repeaters 'collections_detail_images' and checking that the pageField 'collections_detail_image_colour' has the 'collections_colours_group' of 'blue' (for example). If I echo out what $selector is it returns the following (which looks correct) parent=/collections/, collections_detail_images.count>0, sort=name, collections_detail_images=[collections_detail_image_colour.collections_colours_group=blue] But if I echo out the collections_detail_image_colour.collections_colours_group for each they look like '1160collections_colours_group' rather than 'blue' and collections_detail_image_colour.collections_colours_group->name doesn't seem to work). If I echo out 'collections_detail_image_colour->collections_colours_group' it seems to return the correct ID but then I cannot get the name of that, for example: collections_detail_image_colour->collections_colours_group->name or collections_detail_image_colour->collections_colours_group.name doesn't seem to work. Link to comment Share on other sites More sharing options...
a-ok Posted June 27, 2016 Author Share Posted June 27, 2016 Looks like this seems to work... collections_detail_image_colour->collections_colours_group->first()->name But wondering how to return this in the selector... if ($colours != "all") $selector .= ", collections_detail_images=[collections_detail_image_colour.collections_colours_group=$colours]"; Link to comment Share on other sites More sharing options...
a-ok Posted June 27, 2016 Author Share Posted June 27, 2016 <?php $types = $input->get->type; ?> <?php $colours = $input->get->colour; ?> <?php $patterns = $input->get->pattern; ?> <?php $designers = $input->get->designer; ?> <?php $selector = "parent=/collections/, collections_detail_images.count>0, sort=name"; if ($types != "all") $selector .= ", collections_detail_category=$types"; if ($patterns != "all") $selector .= ", collections_detail_pattern=$patterns"; if ($designers != "all") $selector .= ", collections_detail_designer=$designers"; // We make sure we only find pages that have the right colour in one of their repeater items if ($colours != "all") $selector .= ", collections_detail_images.collections_detail_image_colour=[collections_colours_group=$colours]"; ?> <?php $results = $pages->find($selector); ?> <?php include './collections-filters.inc'; ?> <?php if (count($results)) : ?> <div class="container-fluid"> <div class="row"> <div class="fabric-list-container collections-results all"> <?php foreach ($results as $result) : ?> <?php $fabrics = $result->collections_detail_images; $fabrics->sort("collections_detail_image_colour.name"); if ($colours != "all") { $fabrics->filter("collections_detail_image_colour.collections_colours_group.name=$colours"); } ?> <?php foreach($fabrics as $fabric) : ?> <?php include './fabrics-list.inc'; ?> <?php endforeach; ?> <?php endforeach; ?> </div> </div> </div> <?php endif; ?> This is what works! It was just some of the sub-selectors were off/wrong format etc. Many many thanks to @Robin and @LostKobrakai Link to comment Share on other sites More sharing options...
Robin S Posted June 28, 2016 Share Posted June 28, 2016 Glad you got it working. The sub-selector docs are here but I'm sure you found them by now. 1 Link to comment Share on other sites More sharing options...
thetuningspoon Posted August 3, 2018 Share Posted August 3, 2018 This is now possible using owner selectors! http://processwire.com/blog/posts/processwire-3.0.95-core-updates/ $pages->find('template=repeater_collections_detail_images, your_repeater_field.owner.collections_detail_designer=123, include=hidden, sort=name'); 9 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