2016-08-04 51 views
1

VirtualPages的名单我有一个AreaPage$many_manyVirtualPage S:排序在现场从页

class AreaPage extends Page { 

    /** 
    * @var array 
    */ 
    private static $many_many = [ 
     'RelatedVirtualPages' => 'VirtualPage' 
    ]; 

    // ... 

} 

RelatedVirtualPagesContentPage小号复制内容:

class ContentPage extends Page { 

    /** 
    * @var array 
    */ 
    private static $db = [ 
     'Highlighted' => 'Boolean' 
    ]; 

    // ... 

} 

什么是最好的在Highlighted分贝db字段排序RelatedVirtualPages它的复制方法吗?

+1

不应该'RelatedVirtualPages'=>'VirtualPages'是'RelatedVirtualPages'=>'VirtualPage'? – jberculo

+0

是的,你是对的:-)更新的问题 –

回答

3

虚拟页面可能指向不同类型的页面,并且没有强制规定所有这些页面都是ContentPages,或者至少具有Hightlighted db字段的页面。您可以在创建SiteTree时手动确保这一点,但用户可能会过来并将其拧紧,因此请牢记这一点。

下面是一些可能帮助您开始使用的伪代码。它假定所有的虚拟页面都是ContentPages。如果您将有多种VirtualPages引用AreaPage那么这可能是不够的。

$virtualPages = $myAreaPage->RelatedVirtualPages(); 
$contentSourcePages = ContentPage::get()->byIDs($virtualPage->column('CopyContentFromID')); 
$sortedSourcePages = $contentSourcePages->sort('Highlighted','ASC'); 

您可能还可以使用一个innerJoin,但你必须(如果不只是用ContentPage作为VirtualPage再)来处理_Live表以及可能有多个页表这可能导致一些复杂的情况。

更新

所以,在我自己的话总结一下,您需要连接到排序的Highlighted字段中的特定AreaPageContentPage每个VirtualContentPage链接到VirtualContentPages的列表。如果这个结论是准确,将这项工作:

$sortedVirtualPages = $myAreaPage->RelatedVirtualPages() 
->innerJoin('ContentPage', '"ContentPage"."ID" = "VirtualContentPage"."CopyContentFromID"') 
->sort('Highlighted DESC'); 
+0

谢谢你的回答,并指出我的方向。伪代码给了我一个ContentPage的排序列表,但是我需要一个实际的'VirtualPage'列表。我正在考虑做一些类似于获得'VirtualPage'的东西,然后遍历它们,为每个对象添加一个'Highlighted'属性(不写,复制被复制页面的值),然后将它们添加到ArrayList中,然后在“突出显示”上对ArrayList进行排序。思考? –

+0

至于强制页面类型为“ContentPage” - 我忽略了这些部分,以便提供一个简单的问题演示。在实际的代码中,这是通过我扩展VirtualPage('VirtualContentPage','[VCP]')和'VCP'只能存在于'AreaPage'下的事实来处理的,它只能托管'VCP'和'ContentPage '。如果一个编辑器改变'VCP'来从一个'AreaPage'拷贝内容,就会抛出一个验证错误(〜AreaPage'不允许作为'AreaPage'的子元素)。 –

+1

谢谢!您的总结很准确,内部连接解决方​​案绝对是最高效和最干净的解决方案。 –

0

你不能只是做

//just get one areapage 
$AreaPageItem = AreaPage::get()->First(); 

//now get the RelatedVirtualPages sorted 
$related_pages = $AreaPageItem->RelatedVirtualPages()->sort("Highlighted","ASC"); 
+0

由于'Highlighted'列在VirtualPage上不存在,并且会导致MySQL错误,所以很遗憾不起作用。 –

1

我无法找到一个非常干净的方法,但没找到两种方式来实现这一点。该功能发生在类AreaPage
首先

public function getRelatedVirtualPages() 
{ 

    $items = $this->getManyManyComponents('RelatedVirtualPages'); 

    $highlighted = $items->filterByCallback(function($record, $list) { 
     if($record->CopyContentFrom() instanceOf ContentPage) { 
      //return ! $record->CopyContentFrom()->Highlighted; // ASC 
      return $record->CopyContentFrom()->Highlighted; // DESC 
     } 
    }); 

    $highlighted->merge($items); 
    $highlighted->removeDuplicates(); 

    return $highlighted; 
} 

其次我不是很得意的任何这些解决方案(您在注释中描述的方法)

public function getRelatedVirtualPages() 
{ 
    $items = $this->getManyManyComponents('RelatedVirtualPages'); 

    $arrayList = new ArrayList(); 

    foreach($items as $virtualPage) 
    { 
     if($virtualPage->CopyContentFrom() instanceOf ContentPage) { 
      $virtualPage->Highlighted = $virtualPage->CopyContentFrom()->Highlighted; 
      $arrayList->push($virtualPage); 
     } 
    } 

    $arrayList = $arrayList->sort('Highlighted DESC'); 

    return $arrayList; 
} 

,但我相信他们确实符合你的标准。

+1

谢谢!有趣的解决方案1.如果不是因为我需要在另一个字段上进行排序,这是'日期'而不是'布尔值',那么我会去做。解决方案2是我首先想到的,但是觉得它在性能方面很昂贵 - 每次迭代查询数据库(?)。我从AlphaCactus的灵感点修改了一下,只运行了两个查询并保存了结果。看到我的答案 –

1

这里就是我终于实现了,我觉得作品:

/** 
* @return ArrayList 
*/ 
public function VirtualPages() 
{ 

    $result  = []; 
    $virtualPages = $this->RelatedVirtualPages(); 
    $contentPages = ContentPage::get() 
     ->byIDs($virtualPages->column('CopyContentFromID')) 
     ->map('ID', 'Highlighted') 
     ->toArray(); 

    foreach($virtualPages as $virtualPage) { 
     $highlighted = $contentPages[$virtualPage->CopyContentFromID]; 
     $virtualPage->Highlighted = $highlighted; 
     $result[] = $virtualPage; 
    } 

    return ArrayList::create(
     $result 
    ); 

} 

然后它的排序,像这样:

$areaPage->VirtualPages()->sort('Highlighted DESC'); 

感谢您对所有的答案和指针。在标记任何答案之前,我会稍等一会。