Filtering events by day, week, or month

Hi everyone,

I’ve been crawling the forum for a solution but I can’t seem to get this to work with my extremely limited knowledge of PHP…essentially it’s a list of events that each have a start date and end date. What I have right now is that upon landing, every upcoming event is shown.

What I’d like to achieve is some way to toggle between showing events happening during: 1) the current day, 2) a week from the current day, and 3) a month from the current day, with the default view being the week view. Ideally this would take into account the start date and end date of each event as well. I imagine the navigation being either a set of radio buttons or a drop down menu that reloads the page with the correct date range on change.

Everything I’ve gleaned so far seems to employ params as a filtering method but from what I understand, params refer to specific dates rather than relative dates? Or is it possible to to pull the current time, add 24 hours or 7 days or 30 days to that time, and apply it as a range to a param?

All help is highly, highly appreciated, thank you for your time!

I would use simple parameters like today, nextweek, thismonth etc. You can then define in your controller what this means:

<?php
$today = date('Y-m-d');
$nextWeek = mktime(0, 0, 0, date("m")  , date("d")+7, date("Y"));
// etc.

An alternative would DateTime::add

For example:

<?php
$events = $page->children()->visible();
$today = date('Y-m-d');
if($filter = param('time')) {
  if($filter == 'today') {
    $events = $events->filter(function($child) use($today) {
      return $child->date('Y-m-d', 'startdate') == $today;
    });
  }
}

If “thismonth” or “thisweek” is not supposed to be a single day, but a date range, then you have to get the start and end days of these periods and filter by those.

Example:

This week is from today until 7 days later (but we exclude today in the filter):

<?php
 $events = $page->children()->visible();
 $today = date('Y-m-d');
 $thisWeekEnd = date('Y-m-d', mktime(0, 0, 0, date("m")  , date("d")+7, date("Y")));
 if($filter = param('time')) {
   if($filter == 'thisweek') {
     $events = $events->filter(function($child) use($today, $thisWeekEnd) {
       return $child->date('Y-m-d', 'startdate') > $today && $child->date('Y-m-d', 'startdate') <= $thisWeekEnd;
     });
   }
 }

(not tested)

Thank you so much for your help!

This is probably a dumb question but does this go into a controller…? I keep running into the unexpected error page. I tried putting it straight into the template as well, right before looping an event snippet, is that a problem?

And to clarify, the way this param filter is initiated is to go to www.name.com/events/time:thisweek?

Yes.

As regards the error, please turn on debugging in your config.php

c::set('debug', true);

As I said, I didn’t test the code, so their might be an error somewhere.

And yes, the best place is in a controller.

Ahhh it’s working I’m screaming! Thank you so much!

1 Like

What was the problem that caused the error? If it was due to my code, I’d like to correct it…

I think it was because a semi-colon was missing after the $thisWeekEnd variable in your last code block!

How would I go about taking the enddate into account as well? Like even though an event may not have a startdate in the week, it might still be happening during the week. Would it be creating an array for all of the dates between the event’s startddate and enddate and filtering all of them?

And how would I go about selecting the week filter by default on the events page load? Would it be routing?

Thanks again!

Yes, the semicolon was missing, shame on me :blush:

If you want the week as the default, you can simply set $events to a filtered collection:

return function($site, $pages, $page) {
  $today = date('Y-m-d');
  $thisWeekEnd = date('Y-m-d', mktime(0, 0, 0, date("m")  , date("d")+7, date("Y")));
  
// define filtered events as standard
  $events = $page->children()->visible()->filter(function($child) use($today, $thisWeekEnd) {
    return $child->date('Y-m-d', 'startdate') > $today && $child->date('Y-m-d', 'startdate') <=    $thisWeekEnd;
  });
  
  if($filter = param('time')) {
    if($filter == 'today') {
      $events = $page->children()->visible()->filter(function($child) use($today) {
        return $child->date('Y-m-d', 'startdate') == $today;
      });
    }
    if($filter == 'thismonth') {
      $events = $page->children()->visible()->filter(function($child) use($today) {
       return //filtered by month
      });
    }
    // show all events by setting the parameter to "all"
    if($filter == 'all') {
      $events = $page->children()->visible();
    }
  }
  return compact('events', 'filter');
};