如何使用VHS ViewHelper iterator.sort按格式化日期排序记录?
解决TYPO3 Fluid中VHS Iterator.sort的类型错误及排序问题
错误原因
触发的#1256475113错误,核心原因是传入v:iterator.sort的不是纯数组,而是Extbase的QueryResult对象——这类对象在Fluid中会被识别为字符串类型,不符合ForViewHelper对each参数的数组要求。
可行解决方案
1. 先转换为数组再排序
在Fluid中使用f:iterator.toArray()将QueryResult转为纯数组,再传入VHS排序工具:
{# 第一步:按datetime升序排序 #} <f:variable name="sortedByDate" value="{records -> f:iterator.toArray() -> v:iterator.sort(sorting: {datetime: 'ASC'})}" /> {# 后续:按pid升序、datetime升序排序 #} <f:variable name="sortedByPidAndDate" value="{records -> f:iterator.toArray() -> v:iterator.sort(sorting: {pid: 'ASC', datetime: 'ASC'})}" /> {# 遍历排序后的数组 #} <f:for each="{sortedByDate}" as="record"> <p>{record.datetime -> f:format.date(format: 'Y-m-d H:i:s')}</p> </f:for>
2. 控制器层面提前排序(推荐)
避免在视图层处理复杂逻辑,直接在控制器或Repository中完成排序,将纯数组传递给视图:
// 控制器中获取并排序记录 public function listAction() { // 初始按datetime升序排序 $query = $this->recordRepository->createQuery(); $query->setOrderings([ 'datetime' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING ]); $records = $query->execute()->toArray(); // 后续按pid+datetime排序的逻辑 usort($records, function ($a, $b) { // 先比较pid $pidCompare = $a->getPid() <=> $b->getPid(); if ($pidCompare !== 0) { return $pidCompare; } // pid相同时比较datetime return $a->getDatetime() <=> $b->getDatetime(); }); $this->view->assign('records', $records); }
之后在Fluid中直接遍历即可,无需额外处理:
<f:for each="{records}" as="record"> <!-- 渲染记录内容 --> </f:for>
3. 基于DateTime时间戳排序
如果需要在视图层处理DateTime对象的排序,可先将其转为Unix时间戳,再基于时间戳排序:
{# 为每条记录添加时间戳字段 #} <f:variable name="recordsWithTimestamp" value="{records -> v:iterator.map( expression: 'record.datetime -> v:format.date(format: \'U\')', as: 'timestamp' )}" /> {# 按时间戳升序排序(等同于datetime升序) #} <f:variable name="sortedRecords" value="{recordsWithTimestamp -> v:iterator.sort(sorting: {timestamp: 'ASC'})}" /> {# 按pid+时间戳排序 #} <f:variable name="sortedByPidAndTs" value="{recordsWithTimestamp -> v:iterator.sort(sorting: {pid: 'ASC', timestamp: 'ASC'})}" />
内容的提问来源于stack exchange,提问作者ThomasK
相关产品推荐
相关产品推荐

