Template problem: page - dataobject information retrieving

Silverstripe Version: 3.1.x

I want to access dataobject data in a loop, but with a condition consisting of page and dataobject dates

I guess that sounds complicated and maybe I am thinking too complicated.
What I want to accomplish is to list term dates and per term I want to show excluded days e.g. term 2 from 12/04/2019 - 05/07/2019, excluding 02.06. Queens birthday, where the exclusion day is a DataObject (Date, Reason), so I am flexible to add as many as needed.
Now I want to either in the template or in the controller code find out dynamically in which term the exclusion day falls. I tried the following approaches:

  1. attempt:
<% loop ExclusionDates.Sort(Date, ASC) %>
   <% if $Term1Start <  $Date && $Date > $Term1End %>
        <% if First %><div class="term-excl-dates"><% end_if %>
        <% if First %>(<em>excluding: </em></br> &nbsp;<% end_if %> $Date.Nice, $Reason<% if Last %>)<% else %>,<br>&nbsp;<% end_if %><% if Last %></div><% end_if %>
    <% end_if %>
<% end_loop %>

But within the loop I can’t access the $Term1Start/$Term1End from the page, so it ignores this condition and runs through all the Dates.

  1. attempt:
    If I try to sort out the terms in the page controller, I can’t access them in the template as I imagined to.
public function TermOneExclusions(){
        $termStart = $this->Term1Start;
        $termEnd = $this->Term1End;
        $exclusionDays = ExclusionDate::get()->where("\"Date\" > " .  $termStart . "  &&  \"Date\" < " .  $termEnd )->sort("\"Date\" ASC");
           
        return $exclusionDays;
    }

In the template I thought I could access it this way:

<% loop $TermOneExclusions %>
      <% if First %><div class="term-excl-dates"><% end_if %>
      <% if First %>(<em>excluding: </em></br> &nbsp;<% end_if %> $Date.Nice, $Reason
      <% if Last %>)</div><% else %>,<br>&nbsp;<% end_if %>
<% end_loop %>

Here I get nothing except commas…
What part do I not understand?
Can anyone point me in the right direction, please? It would be good if someone could provide me a solution for both my attempts, as I would like to know if there is actually a way to accomplish this with my first attempt and where my problem lies in the second attempt.
Thank you very much!

I would say attempt #2 is the better way to go, but you might be able to get #1 working by using $Up and/or $Top. So to break out of the $ExclusionDates scope and access the page scope you should be able to do e.g. $Top.Term1Start.

In the second attempt (and possibly the first) if you’re just getting commas then there are probably no records in your DataList. If you loop over an empty list in a SilverStripe template it is rendered as if the list contains one item, but all the values are null. (I’d call this a bug but that’s how it is). The better way to structure your loop to prevent this happening is to wrap it in an if block like this:

<% if $TermOneExclusions %>
    <div class="term-excl-dates">
        (<em>excluding:</em>
            <% loop $TermOneExclusions %>
                $Date.Nice, $Reason
                <% if not $Last %><br><% end_if %>
            <% end_loop %>
        )
    </div>
<% end_if %>

This way if $TermOneExclusions is empty, nothing will be rendered.

I’m not sure why your DataList would be empty, but I assume there must be a problem with your TermOneExclusions() method so the next thing I would do is debug that and make sure it’s fetching the records you expect.

Thank you very much for your quick response, JonoM!
That was definitely what I needed. Btw your template formatting is way better than my complicated one. As I mentioned, I probably started to think too complicated when I did my try and errors…

I tried my 1 attempt with the $Top.Term1Start, but it didn’t work properly in regards of the loop. The <% if not $Last >" didn’t work in there. The result looked like this:
( excluding: 17/03/2019, K’s Birthday ,
)

So, I ended up following my second attempt. When I debugged it and tried to execute this in the phpmyadmin SQL I found out that it didn’t give me back any result. When I put my Term1Start date into apostrophie it worked, but I am not 100% convinces that this is really the way to convert this date into a proper string. I am new to PHP, so any hint here for the proper code would be appreciated. Here is my code for this:

public function TermOneExclusions(){
        $termStart = $this->Term1Start;
        $termEnd = $this->Term1End;
                                
        $exclusionDays = ExclusionDate::get()->where("\"Date\" > '" .  $termStart . "'  &&  \"Date\" < '" .  $termEnd . "'")->sort("\"Date\" ASC");
        
        return $exclusionDays;
    }

Thank you very much!

Sorry for the late reply, try this:

$exclusionDays = ExclusionDate::get()
    ->filter([
        "Date:GreaterThanOrEqual" => $termStart,
        "Date:LessThanOrEqual" => $termEnd,
    ])
    ->sort([
        "Date" => "ASC",
    ]);

p.s. most of the time in SilverStripe you don’t need to use ->where as the ORM lets you build a statement more granularly. Take a look at:

And if you haven’t done the SilverStripe lessons, they’re great :slight_smile:

Thank you very much, JonoM!!
That’s exactly what I needed, much more elegant/easier than my code. You are a great tutor!

1 Like