Silverstripe如何将两种页面类型合并为交替排列的SSList
实现两种SilverStripe页面类型的交替排列SSList
方法一:手动交替合并后转SSList
这是最直接的方案,适合数据量不大的场景。核心逻辑就是把两个SSList转成数组,用双指针循环交替取元素,最后把合并后的数组转成ArrayList(SilverStripe里ArrayList是SSList的子类,完全兼容SSList的所有用法)。
代码示例:
$news = BlogPost::get()->sort('PublishedDate'); $projects = ProjectPage::get(); // 转成数组方便操作 $newsItems = $news->toArray(); $projectItems = $projects->toArray(); $mergedList = []; $newsIdx = 0; $projectIdx = 0; // 交替取元素,直到其中一组取完 while ($newsIdx < count($newsItems) && $projectIdx < count($projectItems)) { $mergedList[] = $newsItems[$newsIdx++]; $mergedList[] = $projectItems[$projectIdx++]; } // 把剩下的元素直接追加到末尾 $mergedList = array_merge($mergedList, array_slice($newsItems, $newsIdx)); $mergedList = array_merge($mergedList, array_slice($projectItems, $projectIdx)); // 转成SSList实例 $alternatingList = new ArrayList($mergedList);
方法二:自定义惰性加载集合(适合大数据量)
如果数据量很大,不想一次性把所有数据加载到内存,可以自己写个迭代器类来实现交替遍历,保留SSList的惰性加载特性。
代码示例:
class AlternatingSSList extends SSList { private $listA; private $listB; public function __construct(SSList $listA, SSList $listB) { $this->listA = $listA; $this->listB = $listB; parent::__construct(null); } public function getIterator() { $iterA = $this->listA->getIterator(); $iterB = $this->listB->getIterator(); $hasNextA = $iterA->valid(); $hasNextB = $iterB->valid(); while ($hasNextA || $hasNextB) { if ($hasNextA) { yield $iterA->current(); $iterA->next(); $hasNextA = $iterA->valid(); } if ($hasNextB) { yield $iterB->current(); $iterB->next(); $hasNextB = $iterB->valid(); } } } // 如果需要分页、过滤等功能,需要额外实现对应方法 // 比如 limit()、filter() 等,可直接委托给两个源列表处理后再合并 } // 使用方式 $news = BlogPost::get()->sort('PublishedDate'); $projects = ProjectPage::get(); $alternatingList = new AlternatingSSList($news, $projects);
注意点
- 方法一的
ArrayList支持所有SSList的操作(分页、排序、过滤等),如果需要对合并后的列表做这些操作,直接用就行。 - 方法二的自定义类默认只实现了迭代器,如果需要分页、过滤,得自己加对应的方法——比如在构造前先对两个源列表做分页,或者在自定义类里把这些操作委托给源列表。
内容的提问来源于stack exchange,提问作者galilee
相关产品推荐
相关产品推荐

