Jump to content
RyanJ

Limit selector in foreach not working properly

Recommended Posts

I am using the below to go several levels deep, but when using a select of "limit" or "sort" I am getting strange results. For example, if limit=2 I get five results. If limit=3 I get six results. I am sure I have messed up something.

Maybe there is a better way?

$cats = $pages->get("/mypage/")->children;
// get children of the parent
       foreach ($cats as $cat) {
        $menu .= "<div>";
        $menu .= "<h2 class='titlebg'>$cat->title</h2>";
         if($cat->children) {
// if they have children
           $menu .= "<ul>";
            foreach($cat->children as $subchild) {
             foreach ($subchild->children("limit=2, sort=-date,   
       sort=title") as $child) {
           $menu .= "<li><a href='{$child->url}'>$child->title</a></li>";
         }
        }
         $menu .= "</ul>";
     }
         $menu .= "<span><a href='{$cat->url}'>See More</a></span>";
        $menu .= "</div>";

Share this post


Link to post
Share on other sites

I'm sure there's a better way - if only I knew what you're trying to achieve exactly ;).

Here's an example of a page structure to demonstrate what's happening:

post-481-0-96494100-1384969656_thumb.png

With "limit=2" your code prints out:

cat1
cat2
  child2.1.1
  child2.1.2
  child2.2.1
  child2.2.2
cat3

And with "limit=3":

cat1
cat2
  child2.1.1
  child2.1.2
  child2.1.3
  child2.2.1
  child2.2.2
cat3

Reading the code, it's pretty much expected output to me, but obviously not the one you're after :). You're printing first two (or three) "child" pages under each "subchild" page found under children of "/mypage/" ("cat" pages). (Edit: and leaving all divs open.)

So, what is the output you'd like to see with the page structure outlined above?

(Edit 2: Fixed my examples...)

(Edit 3: Really fixed my examples... It's not my day.)

Edited by nik
  • Like 2

Share this post


Link to post
Share on other sites

Hi Nik,

I am pulling in multiple content areas on one page. I was trying in minimize my code. My goal based off your diagram is to get the grandchildren of cat1, cat2 and cat3 and limit them to 3.

Print Cat1 Title

 Loop through 3 grandchilden of Cat1 and print them

Print Cat2 Title
Loop through 3 grandchilden of Cat2 and print them

Print Cat3 Title
Loop through 3 grandchilden of Cat3 and print them

 I am getting the correct grandchildren for each cat, but the limit part is confusing me. Clear as mud? :).. I also updated my original snippet of code to include the closing div, just forgot to add it when I posted it.

Share this post


Link to post
Share on other sites

First of all, my examples were not right - not at all, sorry. Now they're fixed.

The problem is that you're limiting pages under each "subchild" separately, not all grandchildren at once. Here's one way to get there:

$limit = 4;

$cats = $pages->get("/mypage/")->children;
foreach ($cats as $cat) {
    $menu .= "<div>";
    $menu .= "<h2 class='titlebg'>$cat->title</h2>";
    $grandchildren = $pages->find("parent={$cat->children}, limit=$limit, sort=-date, sort=title");
    if($grandchildren) {
        // if they have GRANDchildren
        $menu .= "<ul>";
        foreach($grandchildren as $child) {
            $menu .= "<li><a href='{$child->url}'>$child->title</a></li>";
        }
        $menu .= "</ul>";
        if($grandchildren->getTotal() > $limit) $menu .= "<span><a href='{$cat->url}'>See More</a></span>";
    }
    $menu .= "</div>";
}

This would give (with the example structure again):

cat1

cat2
  child2.1.1
  child2.1.2
  child2.1.3
  child2.2.1

  See More

cat3
  child3.1.1

This trick to get grandchildren ("parent={$cat->children}") would not be the way to go if there were a lot of "subchild" pages under any "cat" page. This is because the selector expands to something like "parent=1234|1235|1236|1237|...|1507|1508" giving a too long selector string at one point. But assuming there aren't more than a couple of dozen of them, this would work just fine.

I also added a little condition to show "See more" only if there are more grandchildren to see - just as an example.

  • Like 6

Share this post


Link to post
Share on other sites

That is great! You always go the extra mile to explain things in full detail and even with extra details. Makes sense about what was happening. Thanks so much! In time there maybe a lot of sub children, but not for now. May I ask what your approach would be then just for learning purpose?

Share this post


Link to post
Share on other sites

Well, another way would be using a different template for the child pages ("child-template" in the following example). Then you'd be able to fetch the grandchildren like this:

$grandchildren = $pages->find("has_parent=$cat, template=child-template, limit=$limit, sort=-date, sort=title");

This scales really well and has no issues with the length of the selector string. And who knows, maybe you already have things set up in a compatible way. :)

Of course with "has_parent=$cat" you could also filter by some other property that gives you child pages only: "property_abc=only-child-pages-have-this-value". Or filter out the subchildren level with "template!=subchild-template" or "property_xyz!=only-subchild-pages-have-this-value". Those properties and values are naturally only placeholders to demonstrate possible solutions.

The possibilities are more or less endless. Some options, like using different templates, are pretty general but often there are ways specific to the situation available as well.

  • Like 3

Share this post


Link to post
Share on other sites

I had actually added the template=child-template part but was unsure of its effectiveness. template!=a-template even sounds better. It is great to have someone giving you new perspectives and options on how to do/see things differently. It is all too often the brain gets tunnel vision and cannot think of a different solution. I am glad you took the time to make it clear and give a different perspective. Once again, I thank you.

Share this post


Link to post
Share on other sites

@nik, that is exactly what I was looking for because I got stuck with the child of the child of the child pulling and I either need some coffee to wake up or some good sleep and no distraction from the family. You have made my day, man!

 

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By snck
      Hi there,
      I have a problem constructing a selector that finds all pages that refer to pages with a specific template.
      I have pages using an event template and I want to show events based on a specific context. In this example I want to filter the results and only show event pages that relate to a specific template (exhibitions) in their page field related_pages.
      What I tried:
      $events = $pages->find("template=event, related_pages.template.name=exhibition"); Unfortunately it does not work (0 results).
      Same with this:
      $events = $pages->find("template=event, related_pages=[template.name=exhibition]"); At the moment I am helping myself with the following lines, but I have a strong feeling that there is a more efficient solution:
      $events = $pages->find("template=event"); foreach($events as $event){ if(!count($event->related_pages->find("template=exhibition"))){ $events->remove($event); } }  
      I really hope that one of you can help me out.
      Thanks in advance!
      Flo
    • By Kiwi Chris
      The selector in the following code included in a template is returning nothing, however if I take out the compId.resultsdate<={$today} bit, it works fine, although obviously not filtered on the date field.
      $today = strtotime(date('Y-m-d')); $setImages = $pages->find("template=competitionImage, compId={$page->id}, compId.resultsdate<={$today}, compSubject.name=s, imageRating.title=Merit|Honours,check_access=0"); Here's the results of an example from Tracey Debugger
      templates_id=79, resultsdate<=1587729600, status<2048   SELECT pages.id,pages.parent_id,pages.templates_id FROM `pages` JOIN field_resultsdate AS field_resultsdate ON field_resultsdate.pages_id=pages.id AND (((field_resultsdate.data<='2020-04-25 00:00:00' ) )) WHERE (pages.templates_id=79) AND (pages.status<2048) GROUP BY pages.id Over in my ready.php I have inside a hook that refers directly to the page template that's used for the pages in the page field above:
      $today = strtotime(date('Y-m-d')) $event->return = $event->pages->find("template=competition,eventEnd>={$today},eventStart<={$today}"); In this case the filtering on date fields (albeit different ones) works fine. Can anyone suggest why the filter on the date subfield of the page field isn't working?
      Just to confirm, I do have a date value in the field, and it is a date before today. 🙂
      The problem may be something blatantly obvious, but I can't for the life of me figure out why the selector is returning no results when I include the date filter.
    • By Peter Troeger
      Hello Community 🙂
      Has anyone ever tried having multiple elements on one page that get their info with $pages->find('selector, limit=n') and tried using pagination on one of these elements without effecting the other?
      I have a slider on a page where I display content with pagination. But when I go to page two, the slider content also goes to page two, which I don't want it to do 🙂
      Any tips are greatly appreciated!
      Thanks!
      -Peter
    • By Roberts R
      I have simple page structure:
      category subcategory simple-product simple-product simple-product simple-product subcategory .... category2 so Im at category page and running
      $pages->find("template=simple-product, has_parent=$page, limit=8"); and it returns 0 pages
       
      but this returns 4 pages
      $pages->find("template=simple-product, has_parent=$page"); Can someone explain why limit does not work here?
      EDIT:
      So I did some tests and it seems that any limit=n where n is >= actual page count that is possible ... selector return 0 results.
    • By jds43
      Hello, I have a Page Reference by template radio button field to promote a certain page (only two options), but I'd like to target the page that isn't selected. This would be used dynamically throughout the site.
      Does anyone know how I could accomplish this? Would I use something like remove() or not()?
       
×
×
  • Create New...