Запрос ‘orderby’, когда есть несколько значений для одного и того же meta_key

Вопрос или проблема

Я пытаюсь создать настраиваемый сортируемый столбец администратора для пользовательского типа записи, который содержит поле “повторитель”. Плагин, который я использую для этого поля, сохраняет значения как отдельные записи в базе данных под одним и тем же meta_key, но с разными meta_id. Например, что сохранено в базе данных, может быть:

meta_id  post_id  meta_key    meta_value
4516     109      dates_date  1732752000
4518     109      dates_date  1732838400
4520     109      dates_date  1732924800

Поле повторителя содержит даты (временные метки). Я определил два пользовательских столбца администратора: “начальная дата” и “конечная дата”. Я получаю все значения метаданных для ключа dates_date, сортирую их и беру первое значение как начальную дату, а последнее – как конечную. Пока все работает, и столбцы отображают правильные даты.

Я хочу иметь возможность сортировать записи по каждому из этих столбцов. Я использую следующее:

// ... Столбцы зарегистрированы как обычно с использованием
// "manage_{$event_post_type}_posts_columns" и
// "manage_{$event_post_type}_posts_custom_column"


// Зарегистрировать их как сортируемые
add_filter(
    "manage_edit-{$event_post_type}_sortable_columns",
    function (array $columns) {
        $columns['start_date'] = 'start_date';
        $columns['end_date'] = 'end_date';
        return $columns;
    }
);

// Сортировать запрос записей по выбранному столбцу
add_action(
    'pre_get_posts',
    function (\WP_Query $query) {
        $orderby = $query->get('orderby');

        if ($orderby === 'start_date' || $orderby === 'end_date') {
            $meta_query = array(
                'relation' => 'OR',
                array(
                    'key' => $orderby, // start_date или end_date
                ),
                array(
                    'key' => 'dates_date',
                ),
            );

            $query->set('meta_query', $meta_query);
            $query->set('orderby', 'meta_value_num');
        }
    }
);

Причина, по которой у меня есть мета-запрос с двумя условиями OR, заключается в том, что не все записи используют это поле повторителя, и вместо этого некоторые используют отдельные поля start_date и end_date. Я просто оставил это в примере кода для полноты.


Проблема с сортировкой по “конечной дате”, когда используется поле повторителя, которое сохраняет несколько значений для одного и того же dates_date meta_key, заключается в том, что запрос, похоже, берет только первое значение с этим meta_key, и поэтому сортирует их по фактически начальной дате.

Допустим, у меня есть запись с датами 28 ноября, 29 ноября и 30 ноября; и другая запись с датами 27 ноября и 1 декабря. Обратите внимание, что запись A начинается позже записи B, но заканчивается раньше записи B. Хотя столбец “конечная дата” правильно отображает 30 ноября и 1 декабря соответственно, когда я нажимаю на него, чтобы сортировать по конечной дате, на самом деле он ставит вторую запись перед первой, когда сортирует в порядке возрастания, поскольку, похоже, он сравнивает 28 ноября с 27 ноября (их начальные даты):

введите описание изображения здесь

Как я могу сортировать по последнему meta_value с данным meta_key?

Сортировка по нескольким мета-ключам (ссылка) может быть полезна (не протестировано):

add_action( 'pre_get_posts', function ( \WP_Query $query ) {
    $orderby = $query->get( 'orderby' );

    if ( 'start_date' === $orderby || 'end_date' === $orderby ) {
        $meta_query = array(
            'relation' => 'OR',
            'meta_query_1' => array(
               'key' => $orderby, // start_date или end_date
            ),
            'meta_query_2' => array(
                'key' => 'dates_date',
            ),
        );

        $query->set( 'meta_query', $meta_query );

        // Поэкспериментируйте с этим.
        $query->set( 'orderby', array(
            'meta_query_1' => 'ASC',
            'meta_query_2' => 'DESC',
        ) );
    }
} );

Ответ или решение

Упорядочение по мета-значениям с многократными значениями в WordPress

В данном руководстве мы обсудим, как правильно организовать сортировку постов в админке WordPress, если у вас есть пользовательский тип поста с полем "повторитель". Это поле сохраняет свои значения в базе данных с одним и тем же ключом метаданных (meta_key), что может создать сложности при сортировке.

Проблема многократных значений

Как описано в вашем вопросе, значения мета-данных (например, dates_date) сохраняются в базе данных с разными meta_id, что, соответственно, приводит к возможности существования нескольких значений для одного и того же ключа. Это означает, что если вы хотите отсортировать посты по "end date", SQL-запрос, как правило, будет использовать только первое значение, в результате чего происходит неверная сортировка.

Цель

Наша задача состоит в том, чтобы обеспечить правильную сортировку постов по последнему (максимальному) значению мета-значения для заданного ключа, в данном случае для ключа dates_date.

Решение

  1. Настройка мета-запроса: Вам необходимо настроить мета-запрос, чтобы извлекать наибольшее (или последнее) значение meta_value для каждого поста.

  2. Использование агрегатных функций: Для этого вы можете использовать MAX() в SQL-запросе, чтобы получить максимальное значение для каждого поста.

  3. Пример кода:
    Вот пример кода, который поможет вам в достижении цели:

add_action('pre_get_posts', function (\WP_Query $query) {
    if (!is_admin() || !$query->is_main_query()) {
        return;
    }

    $orderby = $query->get('orderby');

    if ($orderby === 'start_date' || $orderby === 'end_date') {
        // Задаем мета-запрос для получения нужных значений
        $meta_query = array(
            'relation' => 'OR',
            array(
                'key' => 'dates_date',
                'compare' => 'EXISTS'
            ),
            array(
                'key' => $orderby
            ),
        );

        $query->set('meta_query', $meta_query);

        // Указываем порядок сортировки
        $query->set('orderby', 'meta_value_num');
        $query->set('meta_key', 'dates_date'); // или 'end_date' если сортируете по этому полю
    }
});

Объяснение кода

  • pre_get_posts: Этот хук позволяет нам вмешиваться в основной запрос WordPress до его выполнения.

  • Условие: Убедимся, что мы работаем только в административной области и с основным запросом.

  • Мета-запрос: Мы создаем meta_query, чтобы учитывать только те посты, которые имеют соответствующие значения мета-данных.

  • Сортировка: Используя meta_value_num, мы указываем, что нам необходимо произвести числовую сортировку.

Заключение

Теперь, когда вы реализовали вышеприведенный код, сортировка по "end date" будет происходить корректно, учитывая максимальные значения из повторяющихся метаданных. Это обеспечит правильное отображение постов в вашем административном интерфейсе.

С помощью этого подхода вы сможете повысить функциональность вашей админки, что очень важно для качественного управления контентом. Правильная сортировка метаданных, особенно в контексте повторяющихся полей, — это критически важный аспект работы с пользовательскими типами постов в WordPress.

Оцените материал
Добавить комментарий

Капча загружается...