Сортировка поля повторителя из расширенных настраиваемых полей в PHP и Timber / Twig

Я пытаюсь отсортировать вывод поля повторителя из расширенных настраиваемых полей (ACF) плагина WordPress, используя реализацию плагина WordPress Timber Twig 1.34. Базовый пример PHP для сортировки из ACF ниже взят из 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_Error_Syntax для "Неизвестного фильтра" с фильтром Twig в Timber мне нужно создать функцию фильтра, которая использует 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;
});

и вызывая фильтр, подобный этому {% for i, row in repeater|sort_timeline %}, в цикле for в view.twig

{% set repeater = timeline %}

       {% for i, row in repeater|sort_timeline %}

          {{ row.date}}

          {{ row.description}}

      {% endfor %}

все, что я получаю, это белый экран и никаких ошибок в журнале php.

FWIW, использование фильтра rot13, такого как {% for i, row in repeater|rot13 %}, также показывает белый экран, так что что-то не так с общим Twig_SimpleFilter.

(Кстати, я также понимаю, что мне может потребоваться преобразовать формат даты php в $row['date'] для правильной сортировки, возможно, используя strtotime, поскольку теперь это просто месяц и год.)

Правильно ли использовать фильтр в Twig? Или можно адаптировать и использовать функцию array_multisort( $order, SORT_DESC, $repeater ); прямо в шаблоне .twig?


Изменить 17.04.18

Код @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;
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
3
0
2 121
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

В 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

Спасибо, это интересно; Я видел примеры настраиваемых фильтров, но не мог заставить их работать. С вашим фильтром я получаю ошибку «Невозможно создать экземпляр абстрактного класса Twig_Filter». Кажется, это связано с новым способом добавления фильтров с использованием Twig_SimpleFunction, но я не знаю.

BlueDogRanch 13.04.2018 03:28

Проверьте свою версию Twig, если это версия 1.x, вам может потребоваться Twig_SimpleFilter.

Thai Duong Tran 13.04.2018 05:17

Я использую 1.34; как мне использовать Twig_SimpleFilter? Использование простейшего примера фильтра rot13 на twig.symfony.com/doc/1.x/advanced.html дает мне фатальную ошибку: неперехваченное исключение 'Twig_Error_Syntax' с сообщением 'Неизвестный фильтр rot13

BlueDogRanch 13.04.2018 18:09

Извините, я думаю, что ошибся там по поводу Twig_SimpleFilter, давно не трогал версию 1.x. Документ, который я опубликовал, относится к версии 2.x, вы можете проверить версию 1.x здесь: twig.symfony.com/doc/1.x/advanced_legacy.html.

Thai Duong Tran 14.04.2018 13:31
Ответ принят как подходящий

Прямое решение на Ваш вопрос.

Попробуйте этот код:

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 %}

Работает! Мне пришлось сменить > на <, чтобы сначала отсортировать самые новые для php5 +. А для php7, насколько я могу судить, usort работает по-другому, и я не понимаю, почему код php7 не работает. stackoverflow.com/questions/44542089/…

BlueDogRanch 16.04.2018 19:33

@BlueDogRanch, как я знаю, оператор космического корабля возвращает -1; 0; 1, а usort требует, чтобы второй аргумент был функцией или закрытием, которое возвращает это -1; 0; 1. Похоже, что в той ссылке, которую вы добавили в комментарий, пользователь каждый раз возвращает -1 - это неверно. Подумайте о стопке карт, которую вы просто берете и кладете на место. Наконец, вы получите результат, в котором первая карта, которую вы возьмете, снова окажется на вершине стопки)

num8er 17.04.2018 01:19

Не знаю про php7; Я посмотрю еще раз. но он отлично работает для php5 +. Спасибо!

BlueDogRanch 17.04.2018 18:53

Другие вопросы по теме