在循环内访问控制器函数 (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);