Jump to content
a-ok

getForPage within a find selector?

Recommended Posts

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?

Share this post


Link to post
Share on other sites

Can't you just do a selector for the field? $pages->find("repeater.count>0")

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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.

repeaters.png

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");

 

  • Like 2

Share this post


Link to post
Share on other sites

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
?>

 

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites

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.

  • Like 1

Share this post


Link to post
Share on other sites

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/

 

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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]";

Share this post


Link to post
Share on other sites
<?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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...