在循环内访问控制器函数 (ChildrenOf)
Access a controller function when inside a loop (ChildrenOf)
我有一个页面类型 (ProducerReport
),它的作用类似于摘要页面 - 它从各个页面 (Shows
) 获取数据并将它们全部列在一个页面上,每个页面都有主要信息文章。
使用 ChildrenOf()
让它变得非常简单,我想哇 SilverStripe 会为我完成所有工作,我所要做的就是构建和设计它!
但是悲剧发生了...
在 Shows
中,我有一个由 $has_many 链接的数据对象,它允许用户为每篇文章添加关键人物,例如联系人等,这是通过 GridField (ShowsContacts
).
起初我假设只需添加必要的变量就可以从 ShowContacts
获取数据 - 这没有用。
然后在视图中我在黑暗中拍了张照片并尝试使用 $ID
它确实有效并返回了 post.
的 ID
所以我继续将它添加到 ProducerReport
控制器中,我希望它能完成工作,允许我执行查询以获取相关联系人并将其循环到 ChildrenOf
循环。
但是,控制器在循环中不执行任何操作。它唯一一次输出任何东西是当我把它放在循环外面的时候。
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 -->
编辑 - 附加代码
这是 ProducerReport
从中获取数据的地方,该模型的所有直接数据都出现在 ChildrenOf
循环中; ShowsContact
数据不可访问,如果我尝试使用 $something($ID)
功能进行查询,它在循环内使用时不起作用。
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;
}
}
我的问题是 - 如果我无法在循环中执行循环,我将如何从另一种页面类型获取数据以及通过关系链接到它的数据 - 或者我做错了什么?
对于您的模板,您可以这样做:
ProducerReport.ss
<% loop Shows %>
<% loop ShowsContacts %>
<%-- contact details here --%>
<% end_loop %>
<% end_loop %>
其中 'ShowsContacts ' 是节目到联系人的关系名称
啊啊啊!! omfg!!!! 好吧,所以在针对这个问题拍了很多很多 之后,我发现了如何让它工作。
解决方法是在循环中使用$Top.[Method]。我认为这是因为 SilverStripe 在循环中做它自己的事情并且出于某种原因变得有点盲目。据我了解 - 你必须告诉方法走出循环才能看到/使用控制器
从上面 ProducerReport.ss
中的代码出发,并根据问题的相关性对其进行删减...
<% 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 %>
我不敢相信我花了这么长时间才找到解决方案!
可能任何遇到类似这样或类似问题的人都能找到答案,因为我真的打算放弃并重写此页面类型的所有内容,并使用查询来获取所有数据以放入模板...
编辑/注意:我发现如果你有一个名为 getUserName
的方法(例如)你不能省略 'get' 与 $Top
一起使用时...所以在模板中使用时需要放置 $Top.getUserName
如果你认为你已经解决了你的问题,我不确定它是否相关,但是 something
控制器方法(甚至使用过吗?)永远不会像任何 DataObject::get()
或 DataList::create()
ORM 总是调用 return DataList
的实例,而不是 DataObject
.
的个体
如果您想查看 SS 从该查询中得到了什么,请尝试使用 ->first()
,您可能会猜到,return 是第一个 DataObject
(或 DataObject
子类)在你的列表中:
...
var_dump(ShowsContact::get()->find('ShowID', $x)->first()->Role);
我有一个页面类型 (ProducerReport
),它的作用类似于摘要页面 - 它从各个页面 (Shows
) 获取数据并将它们全部列在一个页面上,每个页面都有主要信息文章。
使用 ChildrenOf()
让它变得非常简单,我想哇 SilverStripe 会为我完成所有工作,我所要做的就是构建和设计它!
但是悲剧发生了...
在 Shows
中,我有一个由 $has_many 链接的数据对象,它允许用户为每篇文章添加关键人物,例如联系人等,这是通过 GridField (ShowsContacts
).
起初我假设只需添加必要的变量就可以从 ShowContacts
获取数据 - 这没有用。
然后在视图中我在黑暗中拍了张照片并尝试使用 $ID
它确实有效并返回了 post.
所以我继续将它添加到 ProducerReport
控制器中,我希望它能完成工作,允许我执行查询以获取相关联系人并将其循环到 ChildrenOf
循环。
但是,控制器在循环中不执行任何操作。它唯一一次输出任何东西是当我把它放在循环外面的时候。
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 -->
编辑 - 附加代码
这是 ProducerReport
从中获取数据的地方,该模型的所有直接数据都出现在 ChildrenOf
循环中; ShowsContact
数据不可访问,如果我尝试使用 $something($ID)
功能进行查询,它在循环内使用时不起作用。
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;
}
}
我的问题是 - 如果我无法在循环中执行循环,我将如何从另一种页面类型获取数据以及通过关系链接到它的数据 - 或者我做错了什么?
对于您的模板,您可以这样做:
ProducerReport.ss
<% loop Shows %>
<% loop ShowsContacts %>
<%-- contact details here --%>
<% end_loop %>
<% end_loop %>
其中 'ShowsContacts ' 是节目到联系人的关系名称
啊啊啊!! omfg!!!! 好吧,所以在针对这个问题拍了很多很多 之后,我发现了如何让它工作。
解决方法是在循环中使用$Top.[Method]。我认为这是因为 SilverStripe 在循环中做它自己的事情并且出于某种原因变得有点盲目。据我了解 - 你必须告诉方法走出循环才能看到/使用控制器
从上面 ProducerReport.ss
中的代码出发,并根据问题的相关性对其进行删减...
<% 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 %>
我不敢相信我花了这么长时间才找到解决方案! 可能任何遇到类似这样或类似问题的人都能找到答案,因为我真的打算放弃并重写此页面类型的所有内容,并使用查询来获取所有数据以放入模板...
编辑/注意:我发现如果你有一个名为 getUserName
的方法(例如)你不能省略 'get' 与 $Top
一起使用时...所以在模板中使用时需要放置 $Top.getUserName
如果你认为你已经解决了你的问题,我不确定它是否相关,但是 something
控制器方法(甚至使用过吗?)永远不会像任何 DataObject::get()
或 DataList::create()
ORM 总是调用 return DataList
的实例,而不是 DataObject
.
如果您想查看 SS 从该查询中得到了什么,请尝试使用 ->first()
,您可能会猜到,return 是第一个 DataObject
(或 DataObject
子类)在你的列表中:
...
var_dump(ShowsContact::get()->find('ShowID', $x)->first()->Role);