SilverStripe如何从多种页面类型中获取子项(后端和输出)

时间:2016-06-08 17:21:56

标签: silverstripe

我不知道如何只使用单词来写这个问题,所以这里是一个漂亮的小ascii图表,在我开始解释之前我将继续参考...

                                                +-----+
  Department             Department             |Shows |
       +                     +                  +--+--+
       |                     |                     ^
       +->ShowAssignment     +>ShowAssignment       |
                +                                  |
      +------------------------+                   |
      |         |              |                   |
      v         v              v                   |
AssignShow   AssignShow   AssignShow                |
 +                                                 |
 |   +------+                                      |
 +-->Content|                                      |
 |          |                                      |
 +-->Content+--------------------------------------+
 |          |
 +-->Content|
     +------+
顺便说一下 - 前进让我们假装我们试图通过它的3篇儿童文章来获得第一个AssignShow

好的,所以现在你已经看到了什么让我们接受了它。

在每个Department中都有一个ShowAssignment页面,在其下面,每个子页面都是一个AssignShow页面,可以有Content个与特定部门工作相关的页面在节目上做。

Shows页面中,有一个部分可以找到已分配给它的所有部门并在页面上列出。我已经能够检索所有已分配的部门,但似乎无法得到每个部门为该节目所做的所有内容......

更多的视觉效果:)我有大蓝色的部门和静态佛像'我需要这些文章的标题和其页面的链接

More visuals :)

以下是我目前的代码:

Shows.php

 # Get Departments assigned to this show
 public function getAssignedDepartments(){

    $result = new ArrayList();

    # use this shows ID to find out what shows have been selected by departments
    $assignedShowID = AssignShow::get()->filter('ShowsID', $this->ID);

    if(count($assignedShowID) > 0){

        foreach($assignedShowID as $dept){

            $department = Department::get()->byID($dept->DepartmentID);

            $result->add(new ArrayData(array(
                'DepartmentTitle' => $department->Title
                )
            ));

        # This here is where i'm super stuck... I've managed to drill down
        # this far but dont know how to get those darn kids!
        $x = $department
            ->Children()
            ->find('ClassName', 'ShowAssignments')
            ->Children();
        }

        # Title (on the first echo) returns the
        # show title so I know it's targeting correctly...
        foreach ($x as $key) {
            echo $key->Title . '<br>';
            echo $key->Children()->Title . '<br>';
        }

        return $result;
    }
    else
        return null;
 }

总而言之,我最近一次尝试让孩子们获得AssignShow页面的标题,但使用$key->Children()这样的内容并不能让我走一步更深......我需要做什么?

修改,新信息

Righty-o,所以我设法让孩子们能够从bummzack提供的帮助中获取他们的信息

  

更新

     

如果你只需要遍历代码中的层次结构,你应该知道Children是一个List,所以像$ this-&gt; Children() - &gt; Title这样的东西不起作用。你需要这样的东西:

 $children2LevelsBelow = array();
 foreach ($this->Children() as $child) {
    // Go one level deeper…
    foreach ($child->Children() as $subChild) {
        $children2LevelsBelow[] = $subChild;
    }
 }
  

我认为这是与您的问题一起发布的代码中缺少的关键部分。

我目前的代码是这样的(仍在开发中,所以它有点不完整,但上面的答案帮助我更接近)

Show.php

 # Get Departments assigned to this show
 public function getAssignedDepartments(){

     $result = new ArrayList();

     # use this shows ID to find out what shows have been selected in departments
     $assignedShowID = AssignShow::get()->filter('ShowsID', $this->ID);

     if(count($assignedShowID) > 0){

         foreach($assignedShowID as $dept){

             $department = Department::get()->byID($dept->DepartmentID);

             $result->add(new ArrayData(array(
                 'DepartmentTitle' => $department->Title,
                 'Link' => '/film/departments/' . $department->URLSegment
                 )
             ));

             # this gets me what I need... ALMOST -_-
             foreach($dept->Children() as $x) {
                 echo '<br>' . $x->Title . '<br>'; # get AssignShow child Title
                 echo $x->Content; # gets AssignShow child content (not that i need it)
             }
         }
         return $result;
     }
     else
         return null;
 }  

我不明白的是如何在每个部门下输出内容列表...
因此,对于HTML中的每个grid-listing,在下一个块运行之前,它需要1个或更多<li>个... ...

以下是HTML /模板的片段,我将其用于

Shows.ss

 <% loop AssignedDepartments %>

    <div class="grid-listing">

        <h2><a href="$Link">$DepartmentTitle</a></h2>

        <ul>
            <%-- How do I loop in a loop to get a list of ALL li --%>
            <%-- before moving onto the next department in the main loop? --%>
            <li>&rsaquo; <a href="#NoLink">$ContentTitle</a></li>
            <%-- end_loop --%>
        </ul>

    </div><!-- . grid-listing -->

 <% end_loop %>

2 个答案:

答案 0 :(得分:2)

我猜您的关系从ShowsDepartment,可能是has_manymany_many

因此,您应该可以在Shows模板中执行以下操作:

<% loop $Departements %>
<div class="departement">
    <h1>$Title</h1>
    <% loop $Children %>
    <div class="show-assignment">
        <h2>$Title</h2>
        <% loop $Children %>
        <div class="assign-show">
            <h3>$Title</h3>
            <% loop $Children %>
                <div class="content">
                    <h4>$Title</h4>
                </div>
            <% end_loop %>
        </div>
        <% end_loop %>
    </div>
    <% end_loop %>
</div>
<% end_loop %>

虽然它看起来令人着迷,但是这样的模板相当丑陋,如果你打算改变层次结构就不会很好...

相反,您可以在Page类中使用一种特殊方法,以递归方式呈现它的子项。

EG。在Page类中创建这样的方法:

public function RecursiveChildren(){
    return $this->renderWith(array('RC' . $this->ClassName, 'RCPage'));
}

这只是使用RC<ClassName>RCPage模板呈现当前页面,具体取决于可用内容。所需的最小模板为RCPage.ss,可能如下所示。

<div class="$ClassName">
    <h1>$Title</h1>
    <% if $Children %><% loop $Children %>
        $RecursiveChildren
    <% end_loop %><% end_if %>
</div>

您可以做的是用以下内容替换上面的复杂模板:

<% loop $Departements %>
$RecursiveChildren
<% end_loop %>

它将创建与上述复杂模板几乎相同的输出。

要为每种页面类型设计不同的模板,您可以继续创建:RCDepartment.ssRCShowAssignment.ss等,每个模板都负责呈现所述页面类型的片段。

更新

如果您只需要遍历代码中的层次结构,您应该知道ChildrenList,因此$this->Children()->Title之类的内容将无效。你需要这样的东西:

$children2LevelsBelow = array();
foreach ($this->Children() as $child) {
    // Go one level deeper…
    foreach ($child->Children() as $subChild) {
        $children2LevelsBelow[] = $subChild;
    }
}

我认为这是与您的问题一起发布的代码中缺少的关键部分。

答案 1 :(得分:0)

我做到了!这是一个有点复杂的查询,我打算使用SQL,但设法坚持使用SilverStripes ORM。另外,我试图将数据放在同一个函数中并使用相同的$result->add(),这可能就是我发现它如此困难的原因......

这是它的工作方式。

<强> Shows.php
我们获得了分配给我们正在观看的节目的部门。我们为部门的ID输入了一个返回值,我们将在稍后使用

 # Get Departments assigned to this show
 public function getAssignedDepartments(){

     $result = ArrayList::create();

     # use this shows ID to find out what shows have been selected in departments
     $assignedShowID = AssignShow::get()->filter('ShowsID', $this->ID);

     if(count($assignedShowID) > 0){

         foreach($assignedShowID as $dept){

             $department = Department::get()->byID($dept->DepartmentID);

             $result->add(ArrayData::create(array(
                 'Title' => $department->Title,
                 'Link' => '/film/departments/' . $department->URLSegment,
                 'DepartmentID' => $dept->DepartmentID
                 )
             ));
         }

         return $result;
     }
     else
         return null;
 }

<强> Shows.ss
我们使用上面的内容来获得分配给节目的部门并循环播放它们。循环时我们需要第二个循环来获取该部门的子代,我们需要它循环遍历所有子代,然后再进入下一个部门循环。为了确保我们能够获得正确的内容,我们会在DepartmentID中传递以在getDepartmentContent函数中使用

 <% loop AssignedDepartments %>

     <div class="grid-listing">

         <h2><a href="$Link">$Title</a></h2>

         <ul>
             <% loop $Up.getDepartmentContent($DepartmentID) %>
             <li>&rsaquo; <a href="$Link">$Title</a></li>
             <% end_loop %>
         </ul>

     </div><!-- . grid-listing -->

 <% end_loop %>

<强> Shows.php
现在我们得到了孩子,这是我遇到很多麻烦的部分。我们使用我们传入的DepartmentID来帮助我们过滤相关内容,否则它将获得分配给节目的所有内容并将其输出给每个部门,这是不准确的。我们还使用URLSegments

构建网址
 public function getDepartmentContent($DepartmentID){

     # filter result to get the AssignShow which matches this show
     # and the department id supplied param
     $assignedShowID = AssignShow::get()->filter(array(
         'ShowsID' => $this->ID,
         'DepartmentID' => $DepartmentID
         )
     );

     $result = ArrayList::create();

     foreach($assignedShowID as $key){

         foreach($key->Children() as $children){

             # AssignShow
             $assignShow = AssignShow::get()->byID($children->ParentID);

             # ShowAssignment
             $showAssignment = ShowAssignments::get()->byID($assignShow->ParentID);

             # Department
             $department = Department::get()->byID($showAssignment->ParentID);

             # full url path
             $link = $department->URLSegment . '/'
                     . $showAssignment->URLSegment . '/'
                     . $assignShow->URLSegment . '/'
                     . $children->URLSegment;

             $result->add(ArrayData::create(array(
                 'Title' => $children->Title,
                 'Link' => 'film/departments/' . $link
                 )
             ));
         }
     }

     return $result;
 }

这种方式在这里为我提供了我需要以我需要的方式检索的内容。它还保留Controller中包含的所有内容以保持整洁。