I have a page type (ProducerReport
) which acts like a summary page — it gets data from individual pages (Shows
) and lists them all on one page with the main info from each article.
Using ChildrenOf()
made it really easy and simple, I thought wow SilverStripe will do all the work for me all I have to do is structure and style it!
But then tragedy struck...
In Shows
I have a DataObject linked by $has_many which allows users to add key people such as contacts etc for each individual article, this is done via GridField (ShowsContacts
).
At first, I kind of assumed that simply adding the necessary variables would get the data from ShowContacts
— this didn't work.
Then in the view I took a shot in the dark and tried using $ID
which actually worked and returned the ID of the post.
So I went ahead I added this into the ProducerReport
controller which I hoped would get the job done, allowing me to perform a query to get the relevant contacts and loop it within in the ChildrenOf
loop.
However, the controller doesn't do anything while in the loop. The only time it outputs anything is when I put the outside of the loop.
ProducerReport.php
class ProducerReport_Controller extends Page_Controller {
# Get the Show Contacts for the Show, based on ShowsID
public function something($SiteID){
# Needs to be cast to int as param comes in as string
$x = (int)$SiteID;
var_dump(ShowsContact::get()->find('ShowID', $x)->Role);
}
}
ProducerReport.ss
<div class="producer-report">
<% loop ChildrenOf(current-shows).sort('PercentageComplete', 'DESC') %>
<div class="show">
<div class="banner">
<% if $ReportImage %>
$ReportImage
<% else %>
<img src="/assets/_placeholders/producer_report_cover.png" />
<% end_if %>
<a href="$Link" title="View $Title Show Page"><h2>$Title <span>($ProjectCode)</span></h2></a>
</div><!-- . banner -->
<a class="hub-link" target="_blank" href="http://website.com?job=$ProjectCode">Hub</a><!-- . hub-link -->
<div class="stats">
<h3>Show Statistics</h3>
<dl>
<dt>Client</dt>
<% if $Client %>
<dd>$Client</dd>
<% else %>
<dd>None set</dd>
<% end_if %>
</dl>
<dl>
<dt>Percentage Complete</dt>
<% if $PercentageComplete %>
<dd>$PercentageComplete%</dd>
<% else %>
<dd>-</dd>
<% end_if %>
</dl>
</div><!-- . stats -->
</div><!-- . show -->
<!-- Here I need to retrieve info of the contacts belonging to the page -->
<!-- Inside the ChildrenOf loop, this DOESNT output anything -->
$something($ID)
<% end_loop %>
<!-- This outside the loop DOES output a job role -->
$something(84)
</div><!-- . producer report -->
Additional code:
This here is what the ProducerReport
gets data from, all direct data for this Model appears in that ChildrenOf
loop; The ShowsContact
data isn't accessible and if I try to query using the $something($ID)
functionality it doesn't work when used inside the loop.
Shows.php
class Shows extends Page {
private static $db = array(
'ProjectCode' => 'Varchar(4)',
'Client' => 'Varchar(255)',
'PercentageComplete' => 'Int'
);
private static $has_one = array(
'ReportImage' => 'Image'
);
private static $has_many = array(
'ShowsContacts' => 'ShowsContact'
);
public function getCMSFields(){
# GridField / Show Contacts
$conf = GridFieldConfig_RelationEditor::create();
$gridField = new GridField('ShowsContact',
'Show Contact List',
$this->ShowsContacts(), $conf);
$fields->addFieldsToTab('Root.Content.ShowContact', array(
$gridField
));
return $fields;
}
}
class Shows_Controller extends Page_Controller {
# Get key people from ShowsContact class // input via ShowsContact GridField
# THIS HERE is the data that I need displayed on ProducerReport
public function getKeyPeople(){
if($this->ShowsContacts()->exists()){
$result = new ArrayList();
foreach($this->ShowsContacts()->column('MemberID') as $teamMemberID){
$member = Member::get()->byID($teamMemberID);
$result->add(new ArrayData(array(
'PictureURL' => $member->ImageURL,
'Role' => $this->ShowsContacts()->find('MemberID', $teamMemberID)->Role,
'Firstname' => $member->FirstName,
'Surname' => $member->Surname,
'Nickname' => $member->Nickname,
'Email' => $member->Email,
'Ext' => $member->Extension,
'Site' => Site::get()->byID($member->SiteID)->Title
)
));
}
return $result;
}
else
return null;
}
}
How would I get data from another page type as well as data that's linked to it by relationship if I am unable to do a loop within a loop — or am I doing something wrong?
The solution to this is to use $Top.[Method]
inside the loop. I assume it's because SilverStripe is doing its own thing within the loop and for whatever reason becomes a bit blind. From what I understand — you have to tell the method to go outside the loop in order for it to see / use the Controller.
Going from the code above in ProducerReport.ss
and trimming it down for relevance to the question:
<% loop ChildrenOf(current-shows).sort('PercentageComplete', 'DESC') %>
...
$Top.something($ID) <!-- works perfectly, ID is passed. Output is as expected!
...
# Or when in a loop it'll be like so...
<% loop $Top.something($ID) %>
# ArrayList / ArrayData output...
<% end_loop %>
<% end_loop %>
Note: I've found that if you have a method called getUserName
(for example) you cannot omit the 'get' when using it with $Top
, so in the template you need to put $Top.getUserName
when using it.