j__

Listing and filtering contents of repeater fields (similiar to SQL JOIN)

Recommended Posts

On a site that lists events, I am using a repeater field 'event_time', which contains two Inputfield Time fields 'event_time_start' and 'event_time_end'. Some events take place multiple times, others just once. Here's an example for the data structure:

  • event1
    • title: First Event
    • event_time (1):
      • event_time_start: 08:00
      • event_time_end: 09:00
  • event2
    • title: Second Event
    • event_time (1):
      • event_time_start: 08:00
      • event_time_end: 09:00
    • event_time (2):
      • event_time_start: 14:00
      • event_time_end: 18:00
  • event3
    • title: Third Event
    • event_time (1):
      • event_time_start: 07:00
      • event_time_end: 09:30

First, I'd like to generate a list of all events, sorted by event_time_start, with every repeater item added as an actual event (similar to a SQL JOIN clause). The desired output would be:

  • 07:00-09:30 Third Event
  • 08:00-09:00 First Event
  • 08:00-09:00 Second Event
  • 14:00-18:00 Second Event

A selector like

$pages->find('template=event,event_time.event_time_start!=,sort=event_time.event_time_start');

would only return each event page once:

  • 07:00-09:30 Third Event
  • 08:00-09:00 First Event
  • 08:00-09:00 Second Event

without

  • 14:00-18:00 Second Event

Is there a possible alteration of the selector to take all different occurrences into account?

Also I'd like to filter for events taking place in the morning, using a selector like:

$pages->find('template=event,event_time.event_time_start>=06:00,event_time.event_time_start<=12:00,sort=event_time.event_time_start');

However, this would only return each 'event' page, which then contains also the afternoon version of event2.

While I have the impression these are rather simple tasks, I struggle finding a selector-based solution to it. In this example on opening times are some similarities, but it does not deal with multiple occurrences. I'd appreciate your ideas to it.

Share this post


Link to post
Share on other sites

Hello @j__,

using a Repeater field for this use case may be nice on the back-end but as you have already experienced difficult to output.

One possibility could be to build yourself a new PageArray, where you add all repeater items and sort or filter them however you like.

Or you could reconsider and use regular pages for your events. 😉

Regards, Andreas

  • Like 1

Share this post


Link to post
Share on other sites

You could use a selector to match the repeater pages (according to their template) and then get their owner pages (the events) with getForPage().

// You need check_access=0 to match repeater pages for non-superusers
$repeater_items = $pages->find("template=repeater_event_time, event_time_start>=06:00, event_time_start<=12:00, sort=event_time_start, check_access=0");
foreach($repeater_items as $repeater_item) {
    $owner_page = $repeater_item->getForPage();
    // Use $repeater_item and $owner_page as needed to build the event/time string
    // ...
}

 

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 celfred
      Hello,
      I'm facing a weird behavior (to me)... Why are these requests not returning the same values ?

        // Test 01 : not working > returns empty $allPlayers = $pages->find("team=$team"); // Returns the 10 players (1 of them has HP=14, others have HP>15, no players have coma=1) $dangerPlayers = $allPlayers->find("(HP<=15), (coma=1)")->sort("coma, HP"); // Returns nothing ??? // Test 02 : Working as expected $dangerPlayers = $pages->find("parent.name=players, team=$team, (HP<=15), (coma=1)")->sort("coma, HP"); // Returns the low HP player
      If you can explain this to me, I would appreciate because this is causing me a headache right now 🙂 
      Thanks !
    • By ridgedale
      Reference: PW 3.0.111 and uikit3 based site using the Regular-Master profile.
      I am trying to add a field that provides a dropdown menu but there are no Options or Selector(s) type available - see attached image of field types available.
      The following reference under the docs does not appear to be applicable any more:
      https://processwire.com/api/modules/select-options-fieldtype/
      I can't see how to achieve this. Any assistance would be appreciated.

    • By jothanne
      I have the following page and field setup:
      root_page (Page)
      |
      |- colors_page (Page)
      |  |
      |  |- type_repeater (Repeater Field)
      |     |
      |     |- color_repeater (Repeater Field)
      |        |- colorname_text (Text Field)
      |        |- coloropt_options (Select Options Field / Multiple values)
      |           (1=usable, 2=preferred)
      |
      |- products_page (Page)
         |
         |- product_repeater (Repeater Field)
            |- product_color (Page Reference Field)
      Now i want to fill the entries of the 'product_color'-field with only the color names ('colorname_text'-field) of the colors which are 'usable' (value=1) corresponding to the 'coloropt_options'-field within the nested repeaters 'type_repeater' and 'color_repeater' of the 'colors_page'.
      I researched and tried a lot, but cant't really get around this problem. As a temporary workaround i replaced the repeater fields by subpages - but that isn't what i want in the end. And now i hope for a helping hand to give me the essential advice or hint.
      Thanks a lot in advance.
    • By karian
      I don't know why multiple instances (repeater_repeat_columns1, repeater_repeat_columns2, ...) of my repeater field are displayed inside Template field (see image).
      Is there a way to clean/reset it ?
       

    • By dragan
      I'm trying to update certain repeater fields with a hook. This almost works, but is somehow buggy.
      Each repeater is supposed to represent a row: service, remarks, number of days, day-rate, row total.
      The last repeater should then show the grand total.
      I've tried this:
      $this->addHookAfter("Pages::saveReady", function (HookEvent $event) { $page = $event->object->getPage(); if ($page->template->id == 89 && $page->parent->parent->id == 11180) { $repeater = $page->offer_calc_repeater; $itemCount = $repeater->count(); $c = 0; $grandTotal = 0; foreach ($repeater as $rep) { if($c < ($itemCount - 1) ) { if (!empty($rep->days) && !empty($rep->daily_rate)) { $num_days = $rep->days; $day_rate = $rep->daily_rate; $row_total = $num_days * $day_rate; $rep->row_total = $row_total; $grandTotal = $grandTotal + $row_total; $page->save(); unset($num_days); unset($day_rate); unset($row_total); $c++; } } if ($c == $itemCount) { $rep->row_total = $grandTotal; } } } }); Most calculations are correct, but:
      The first one is empty.
      The second one is calculated wrong.
      I've tried typecasting (float), or checking with strlen instead of !empty, but that doesn't make any difference.
      Is the Pages::saveReady the ideal hook for such stuff? (placed in site/ready.php).
      Also, I get an error message: Session: Method Pages::getPage does not exist or is not callable in this context.
      Any ideas? Would you perhaps rather do stuff like this via JS?