从 PHP 和 Timber/Twig 中的高级自定义字段对转发器字段进行排序
Sorting a repeater field from Advanced Custom Fields in PHP and Timber/Twig
我正在尝试使用 Twig 1.34 的 WordPress Timber 插件实现对来自 WordPress 插件高级自定义字段 (ACF) 的转发器字段的输出进行排序。从下面的 ACF 中排序的基本 PHP 示例来自 https://www.advancedcustomfields.com/resources/how-to-sorting-a-repeater-field/,并且在 ACF 论坛中没有针对我的问题的可用答案。
所以我正在尝试将此函数从示例转换为 Timber/Twig:
// get repeater field data
$repeater = get_field('repeater');
// vars
$order = array();
// populate order
foreach( $repeater as $i => $row ) {
$order[ $i ] = $row['id'];
}
// multisort
array_multisort( $order, SORT_DESC, $repeater );
// loop through repeater
if( $repeater ): ?>
<ul>
<?php foreach( $repeater as $i => $row ): ?>
<li><?php echo $row['id']; ?>. <?php echo $row['name']; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
下面是我在 view.twig
文件中实现的内容。我的 ACF 转发器字段称为时间线,有两个子字段,日期和描述。
{% set repeater = timeline %}
{% for i, row in repeater %}
{{ row.date}}
{{ row.description}}
{% endfor %}
输出ACF中继器的现有字段(一个数组)timeline
——日期和描述两个字段——按照从旧到早的日期顺序,这是默认的,像这样:
Jan 2010
Lorum Ipsum blah blah blah
Jul 2011
Lorum Ipsum blah blah blah Lorum Ipsum
但我想先按最新日期排序。
根据这个答案 我需要创建一个过滤器函数,它使用 Twig_SimpleFilter
并对转发器字段数组进行排序。
我已经测试过了,那个答案中的示例 rot13
过滤器适用于 {{ 'test text'|rot13 }}
。
但是当尝试将相同的 Twig_SimpleFilter
结构与代码一起使用以按日期对数组进行排序时,即在我的主题 functions.php
文件中使用它:
add_filter('timber/twig', function($twig) {
$twig->addExtension(new Twig_Extension_StringLoader());
$twig->addFilter(
new Twig_SimpleFilter(
'sort_timeline',
function($string) {
$repeater = get_field('timeline');
$order = array();
foreach( $repeater as $i => $row ) {
$order[ $i ] = $row['date'];
}
array_multisort( $order, SORT_DESC, $repeater );
}
)
);
return $twig;
});
并在 view.twig
中的 for 循环中像这样调用过滤器 {% for i, row in repeater|sort_timeline %}
{% set repeater = timeline %}
{% for i, row in repeater|sort_timeline %}
{{ row.date}}
{{ row.description}}
{% endfor %}
我得到的只是白屏,php 日志中没有错误。
FWIW,使用像 {% for i, row in repeater|rot13 %}
这样的 rot13
过滤器也会显示白屏,所以整体 Twig_SimpleFilter
.
有问题
(顺便说一句,我也意识到我可能需要转换 $row['date']
中的 php 日期格式才能正确排序,也许使用 strtotime
,因为现在只是月份和年份。)
在 Twig 中使用过滤器是否是尝试此操作的正确方法?或者是否可以直接在 .twig
模板中改编和使用 array_multisort( $order, SORT_DESC, $repeater );
函数?
编辑 2018 年 4 月 17 日
@num8er 的代码适用于 php5+。 php7 运算符似乎是个问题。
并且,下面的另一个函数将对转发器的后端行进行排序;更改值并添加到主题的 functions.php
文件中。参见 https://support.advancedcustomfields.com/forums/topic/sort-repeater-in-back-end-where-data-is-entered/
要获取要排序的行的 MySQL field_123456789
名称,请转至 ACF 导出页面并导出字段组。 https://support.advancedcustomfields.com/forums/topic/how-to-retrieve-a-group-field-key/
add_filter('acf/load_value/name=timeline', 'my_acf_load_value', 10, 3); //repeater name is timeline
function my_acf_load_value( $rows)
{
foreach( $rows as $key => $row ) {
$column_id[ $key ] = $row['field_5967e7639a09b'];
}
array_multisort( $column_id, SORT_DESC, $rows );
return $rows;
}
在 Twig 中,您可以创建自定义过滤器并将其添加到 运行 Twig 环境中。这样,您就可以创建自己的 multisort
过滤器:
$multisort_filter = new Twig_Filter('multisort', function ($repeaters) {
$order = array();
foreach( $repeaters as $i => $row ) {
$order[ $i ] = $row['id'];
}
// multisort
array_multisort( $order, SORT_DESC, $repeaters );
return $repeaters;
});
然后将其添加到树枝中:
$twig = new Twig_Environment($loader);
$twig->addFilter($filter);
现在您可以从模板中调用 multisort
过滤器。
{% for i, row in repeater|multisort %}
{{ row.date}}
{{ row.description}}
{% endfor %}
可以在他们的文档中找到有关扩展 Twig 的更多信息:https://twig.symfony.com/doc/2.x/advanced.html
直接解决您的问题。
试试这个代码:
add_filter('timber/twig', function($twig) {
$twig->addExtension(new Twig_Extension_StringLoader());
$twig->addFilter(
new Twig_SimpleFilter(
'timeline_latest_first',
function($timeline) {
usort($timeline, function($a, $b) {
if(strtotime($a['date']) === strtotime($b['date'])) return 0;
return strtotime($a['date']) > strtotime($b['date']) ? -1 : 1;
// or simply (if php 7.x):
// return -1*(strtotime($a['date']) <=> strtotime($b['date']));
});
return $timeline;
}
)
);
return $twig;
});
{% set timeline_sorted = timeline|timeline_latest_first %}
{% for i, row in timeline_sorted %}
{{ row.date}}
{{ row.description}}
{% endfor %}
我正在尝试使用 Twig 1.34 的 WordPress Timber 插件实现对来自 WordPress 插件高级自定义字段 (ACF) 的转发器字段的输出进行排序。从下面的 ACF 中排序的基本 PHP 示例来自 https://www.advancedcustomfields.com/resources/how-to-sorting-a-repeater-field/,并且在 ACF 论坛中没有针对我的问题的可用答案。
所以我正在尝试将此函数从示例转换为 Timber/Twig:
// get repeater field data
$repeater = get_field('repeater');
// vars
$order = array();
// populate order
foreach( $repeater as $i => $row ) {
$order[ $i ] = $row['id'];
}
// multisort
array_multisort( $order, SORT_DESC, $repeater );
// loop through repeater
if( $repeater ): ?>
<ul>
<?php foreach( $repeater as $i => $row ): ?>
<li><?php echo $row['id']; ?>. <?php echo $row['name']; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
下面是我在 view.twig
文件中实现的内容。我的 ACF 转发器字段称为时间线,有两个子字段,日期和描述。
{% set repeater = timeline %}
{% for i, row in repeater %}
{{ row.date}}
{{ row.description}}
{% endfor %}
输出ACF中继器的现有字段(一个数组)timeline
——日期和描述两个字段——按照从旧到早的日期顺序,这是默认的,像这样:
Jan 2010
Lorum Ipsum blah blah blah
Jul 2011
Lorum Ipsum blah blah blah Lorum Ipsum
但我想先按最新日期排序。
根据这个答案 Twig_SimpleFilter
并对转发器字段数组进行排序。
我已经测试过了,那个答案中的示例 rot13
过滤器适用于 {{ 'test text'|rot13 }}
。
但是当尝试将相同的 Twig_SimpleFilter
结构与代码一起使用以按日期对数组进行排序时,即在我的主题 functions.php
文件中使用它:
add_filter('timber/twig', function($twig) {
$twig->addExtension(new Twig_Extension_StringLoader());
$twig->addFilter(
new Twig_SimpleFilter(
'sort_timeline',
function($string) {
$repeater = get_field('timeline');
$order = array();
foreach( $repeater as $i => $row ) {
$order[ $i ] = $row['date'];
}
array_multisort( $order, SORT_DESC, $repeater );
}
)
);
return $twig;
});
并在 view.twig
{% for i, row in repeater|sort_timeline %}
{% set repeater = timeline %}
{% for i, row in repeater|sort_timeline %}
{{ row.date}}
{{ row.description}}
{% endfor %}
我得到的只是白屏,php 日志中没有错误。
FWIW,使用像 {% for i, row in repeater|rot13 %}
这样的 rot13
过滤器也会显示白屏,所以整体 Twig_SimpleFilter
.
(顺便说一句,我也意识到我可能需要转换 $row['date']
中的 php 日期格式才能正确排序,也许使用 strtotime
,因为现在只是月份和年份。)
在 Twig 中使用过滤器是否是尝试此操作的正确方法?或者是否可以直接在 .twig
模板中改编和使用 array_multisort( $order, SORT_DESC, $repeater );
函数?
编辑 2018 年 4 月 17 日
@num8er 的代码适用于 php5+。 php7 运算符似乎是个问题。
并且,下面的另一个函数将对转发器的后端行进行排序;更改值并添加到主题的 functions.php
文件中。参见 https://support.advancedcustomfields.com/forums/topic/sort-repeater-in-back-end-where-data-is-entered/
要获取要排序的行的 MySQL field_123456789
名称,请转至 ACF 导出页面并导出字段组。 https://support.advancedcustomfields.com/forums/topic/how-to-retrieve-a-group-field-key/
add_filter('acf/load_value/name=timeline', 'my_acf_load_value', 10, 3); //repeater name is timeline
function my_acf_load_value( $rows)
{
foreach( $rows as $key => $row ) {
$column_id[ $key ] = $row['field_5967e7639a09b'];
}
array_multisort( $column_id, SORT_DESC, $rows );
return $rows;
}
在 Twig 中,您可以创建自定义过滤器并将其添加到 运行 Twig 环境中。这样,您就可以创建自己的 multisort
过滤器:
$multisort_filter = new Twig_Filter('multisort', function ($repeaters) {
$order = array();
foreach( $repeaters as $i => $row ) {
$order[ $i ] = $row['id'];
}
// multisort
array_multisort( $order, SORT_DESC, $repeaters );
return $repeaters;
});
然后将其添加到树枝中:
$twig = new Twig_Environment($loader);
$twig->addFilter($filter);
现在您可以从模板中调用 multisort
过滤器。
{% for i, row in repeater|multisort %}
{{ row.date}}
{{ row.description}}
{% endfor %}
可以在他们的文档中找到有关扩展 Twig 的更多信息:https://twig.symfony.com/doc/2.x/advanced.html
直接解决您的问题。
试试这个代码:
add_filter('timber/twig', function($twig) {
$twig->addExtension(new Twig_Extension_StringLoader());
$twig->addFilter(
new Twig_SimpleFilter(
'timeline_latest_first',
function($timeline) {
usort($timeline, function($a, $b) {
if(strtotime($a['date']) === strtotime($b['date'])) return 0;
return strtotime($a['date']) > strtotime($b['date']) ? -1 : 1;
// or simply (if php 7.x):
// return -1*(strtotime($a['date']) <=> strtotime($b['date']));
});
return $timeline;
}
)
);
return $twig;
});
{% set timeline_sorted = timeline|timeline_latest_first %}
{% for i, row in timeline_sorted %}
{{ row.date}}
{{ row.description}}
{% endfor %}