【问题标题】:Silverstripe 3 template loops functions and nested loopsSilverstripe 3 模板循环函数和嵌套循环
【发布时间】:2014-11-19 15:04:47
【问题描述】:

早上好,

我一直在与 Silverstripe 作斗争,它正在对嵌套循环和循环内的函数进行模板解析一段时间,这变得令人抓狂。

如果我能得到除 ajax 之外的替代解决方案(它必须是纯 php/html/ss),那将是可以接受的,谢谢。

[情况]
我有 2 个数据对象:ObjectA [has_many ObjectB] 和 ObjectB [has_one ObjectA]。
我已经使用 CSS-Bootstrap 实现了一个选项卡窗格,并希望在各自的选项卡中显示这两个链接的对象。

示例:
ObjectA_Car 映射到 [ObjectB_Process1, ObjectB_Process2]
ObjectA_Plane 映射到 [ObjectB_Process3, ObjectB_Process4]

场景 1:
请参阅下面的示例伪代码:

///>sample.ss snippet
<% loop ObjectA_DataList %>
    <div class="tab-pane">
        <h3>$ObjectA_DataList.Title</h3> <!-- Prints ObjectA Title -->
        <hr />
        <h4>$ObjectA_DataList.Description</h4> <!-- Prints ObjectA Description -->
        DEBUG: $Pos <!-- Prints ObjectA loop count/index -->

        <!-- PROBLEM STARTS HERE -->    
        <% loop ObjectB_DataList %>
             DEBUG: ObjectA Count: $Top.Pos <!-- Always prints 1, regardless -->
             DEBUG: ObjectA Count2: $Up.Pos <!-- Same issue as above -->
             DEBUG: $Pos <!-- due to scope, this now prints ObjectB loop count/index -->
        <% end_loop %>
    </div> <!--//#tab-pane-->
<% end_loop %>   

我在上面示例中的目的是尝试将 ObjectB 循环内的 ObjectA $Pos 与属于 ObjectB 的 ID 进行匹配。不工作,因为我无法在 ObjectB 中获取 ObjectA 当前循环 $Pos。

场景 2:
接下来我尝试使用一个函数。

///>sample extension code
public function testfn(){
    return "<pre>testfn called!</pre>";
}//testfn

///>sample.ss
$testfn <!-- WORKS OUTSIDE OF LOOP -->
<% loop ObjectA_DataList %>
    $testfn <!-- DOES NOT WORK! -->
<% end_loop %>

场景 3
我厌倦了试图让上述场景发挥作用,然后尝试使用控制器。
因此,我决定将一个 ArrayList 传递给模板,并使用一个循环对其进行迭代。
但是,我似乎无法获得价值。见下文:

///>sample_controller.php
public function sample(SS_HTTPRequest $request){
    ///... snippet ...
    $buildArr = array();
    foreach($ObjectA as $objA){
       $buildArr[$objA->ID]['objA'] = $objA; //store ObjectA
       $objB = ObjectB::get()->filter(array('Status'=>'Enabled','ObjectA_ID'=>$objA->ID));
       $buildArr[$objA->ID]['objB'] = $objB; //store ObjectB
    }//foreach loop

    $sample_data = new ArrayList($buildArr);
    //if I do a var_dump here, everything looks great.
    //so nothing seems to be the problem with the $sample_data array

    $data = array('mysample' => $sample_data);
    return $this->customise($data)->renderWith(array('sample', 'Page'));
}//sample

///>sample.ss
<% loop mysample %>
      <!-- I don't know how to get the data out -->
      <!-- I've tried $Title, $mysample.Title, $mysample.ObjectA.Title -->
      <!-- nothing seems to work. -->
<% end_loop %>

非常感谢您提供的任何帮助,谢谢。

【问题讨论】:

    标签: function loops controller nested silverstripe


    【解决方案1】:

    早上好!

    我可以帮助您使用场景 2 和 3 找到解决方案。对于第一个问题,我不知道如何正确解决第一个循环的范围。

    场景 2

    这个很简单。你只需要参考一般范围Top:

    ///>sample extension code
    public function testfn(){
        return "<pre>testfn called!</pre>";
    }//testfn
    
    ///>sample.ss
    $testfn <!-- WORKS OUTSIDE OF LOOP -->
    <% loop ObjectA_DataList %>
        $Top.testfn <!-- SHOULD WORK LIKE THIS -->
    <% end_loop %>
    

    场景 3

    我调整了第三个场景来完成这里的工作:

    ///>sample_controller.php
    public function sample(SS_HTTPRequest $request){
        // get ObjectA
        $ObjectA = ObjectA::get();
    
        // run through all ObjectA and add the
        // information from ObjectB to a list of both
        $data = new ArrayList();
        foreach($ObjectA as $objA){
            $objB = ObjectB::get()->filter(array(
                'Status' => 'Enabled',
                'ObjectA_ID' => $objA->ID
            ));
            $data->add(array(
                'ObjA' => $objA,
                'ObjB' => $objB
            ));
        }//foreach loop
    
        return $this->customise(array('mysample' => $data))
            ->renderWith(array('sample', 'Page'));
    }//sample
    
    ///>sample.ss
    <% loop $mysample %>
        <!-- for a single DataObject -->
        <p>ObjA: $ObjA.ID</p>
    
        <!-- for a DataList -->
        <% loop $ObjB %>
            <p>ObjB: $ID</p>
        <% end_loop %>
    <% end_loop %>
    

    这种方法应该适用于单个 DataObject 以及 DataList(类似于 ArrayList)。根据您添加到控制器中的 ArrayList 的数据,您需要调整 SS 文件。

    如果您还有其他问题,请告诉我。

    免责声明:未经测试且没有任何保证,应该仍然有效

    【讨论】:

    • 我通常会连本带利的把钱还给我。这可能就是为什么我的错误答案总是很受欢迎的原因。但考虑到场景 2 和 3,我必须同意 @spekulatius。我也对场景 1 非常感兴趣,因为我遇到了同样的问题。也许可以对从控制器返回的模板部分做一些事情,这样您就可以将模板与普通代码混合使用?
    • @spekulatius:非常感谢。您的两种解决方案都有效。在场景 3 中,您在获取 $ObjectA 的开头有一个小错字。它应该是 $ObjectA = ObjectA::get(),你犯了一个错误并将 B 分配给 A,而且 ArrayList 的构造函数也需要一个数组参数。所以, new ArrayList() 应该是 new ArrayList(array());感谢一百万,出色的解决方案。
    • 关于“jberculo”评论的后半部分:“也许可以对从控制器返回的模板部分做一些事情,这样你就可以将模板与普通代码混合使用?”。我同意那个。会有很大帮助的。
    • 我修复了 ObjectB::get()。关于数组列表。可以使用数组或不使用数组来调用它。 "__construct(array $items = array()) {" 如果没有给出任何参数,则默认设置一个空数组。对于场景#1,我仍在考虑解决方案。如果我来了,我会添加它。
    • 任何包装在 HTMLCode-Object 中的返回都将被打印出来。这通常通过使用 forTemplate 函数来完成。您可以在以下位置找到更多信息:groups.google.com/forum/#!topic/silverstripe-dev/Cw8pmtuBd_0 如果您对此有任何疑问,请提出另一个问题 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2012-10-25
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多