Что делают add_filters() и apply_filter()?

23 авг. 2011 г., 15:18:25
Просмотры: 18.7K
Голосов: 5

Я немного запутался, почему это не работает — хотя надо сказать, я не совсем уверен, что именно делают функции apply_filters() и add_filter(), поэтому любые общие подсказки тоже будут очень полезны!

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

function sw_filter_posts_before( $where = '', $date) {

    $where .= " AND post_date < '" . $date . "'"; // Добавляем условие для даты
    return $where;
}

Как правильно применить этот фильтр? Простое использование add_filter или apply_filter перед созданием нового объекта WP_Query не срабатывает.

Заранее спасибо!

Редактирование: Чтобы углубиться в тему, я хотел бы понять, как передать переменную в фильтр, так как у меня не получается передать $date из другой функции.

Вот та самая другая функция (это AJAX-вызов в WordPress, поэтому я сначала получаю ID текущего поста через переменную $_POST):

function create_more_videos_sidebar() {

    $id = $_POST['theID']; // Получаем ID поста из AJAX-запроса

    $args = array(  'post_type'         =>  'videos', // Тип поста — видео
                    'posts_per_page'    =>  1,        // Один пост
                    'p'             =>  $id          // Конкретный ID поста
                ); 

    $wp_query = new WP_Query($args);

    while ($wp_query->have_posts()) : $wp_query->the_post(); $do_not_duplicate = $post->ID;

        $date = get_the_date('Y-m-d'); // Получаем дату поста в формате Y-m-d

    endwhile;

    $args = array(  'post_type'         =>  'videos', // Тип поста — видео
                    'posts_per_page'    =>  5         // Пять постов
                ); 

    add_filter( 'posts_where', 'sw_filter_videos_before' ); // Добавляем фильтр, но не знаем, как передать $date


    $wp_query = new WP_Query($args);
    remove_filter( 'posts_where', 'sw_filter_videos_before' ); // Удаляем фильтр после использования

    // Здесь код цикла...

    $response = json_encode( array( 'result' => $result ) );

    header( "Content-Type: application/json" );
    echo $response;

    exit;
}
3
Комментарии

Хорошо, начнем с самого главного: к какому именно хуку вы пытаетесь добавить свой фильтр? Это важно, потому что ваша переменная $date использует данные $post, поэтому нам нужно знать, фильтруем ли мы внутри или вне цикла (Loop).

Chip Bennett Chip Bennett
23 авг. 2011 г. 17:31:31

Думаю, именно здесь меня подводит недостаток знаний о фильтрах WordPress. Я предполагал, что хук 'posts_where' должен добавить заданную строку в SQL-запрос. Насколько я понимаю, это происходит вне цикла, так как это часть предварительной обработки перед созданием цикла. Есть ли у вас предложение, как лучше всего реализовать мою задачу?

Michael Watson Michael Watson
23 авг. 2011 г. 19:27:38

Конечно, мы сможем это сделать. :) Какую дату вы хотите использовать? Или, если точнее: как вы хотите определить, какую дату использовать?

Chip Bennett Chip Bennett
23 авг. 2011 г. 20:53:28
Все ответы на вопрос 1
7

Что вы пытаетесь отфильтровать? Предположу, что вы хотите добавить фильтр к хуку posts_before. В этом случае вам нужно добавить свой фильтр к этому хуку через add_filter():

function mytheme_filter_posts_before( $where = '', $date) {

    $where .= " AND post_date < '" . $date . "'";
    return $where;
}
// Добавляем функцию к хуку фильтра
add_filter( 'posts_before', 'mytheme_filter_posts_before' );

Обратите внимание, что я изменил название вашей функции. filter_posts_before() — слишком общее имя для функции, что с высокой вероятностью может вызвать конфликт имен.

РЕДАКТИРОВАТЬ

Для ясности:

  • apply_filters() — это место вызова хука фильтра, вызывается ядром WordPress и используется для применения всех фильтров, добавленных в очередь темами/плагинами (и ядром).
  • add_filter() вызывается темами/плагинами (и ядром) и используется для добавления фильтров в очередь, которые затем применяются к хуку ядром.

РЕДАКТИРОВАТЬ 2

Судя по вашему комментарию, хук называется posts_where. Давайте попробуем переписать вашу функцию-обработчик:

function mytheme_filter_posts_where( $where ) {

    // Здесь нужно определить, какую дату использовать. 
    // В вашем примере вызывается get_the_date(),
    // но эта функция работает только внутри Цикла.
    // Попробуем get_the_time().
    // Вам нужно будет определить, какой ID записи использовать.
    $post = 'some_post_id';
    $date = get_the_time( 'Y-m-d', $post );

    $where .= " AND post_date < '" . $date . "'";
    return $where;
}
// Добавляем функцию к хуку фильтра
add_filter( 'posts_where', 'mytheme_filter_posts_where' );
23 авг. 2011 г. 15:26:20
Комментарии

Спасибо за разъяснения! Я обязательно переименую фильтр. Я все еще не понимаю, как передать переменную $date в этот фильтр, не могли бы вы тоже это уточнить? Спасибо!

Michael Watson Michael Watson
23 авг. 2011 г. 15:34:12

Что представляет собой переменная $date и откуда она берется?

Chip Bennett Chip Bennett
23 авг. 2011 г. 15:38:27

Переменная $date приходит из другой моей функции, это дата текущей записи в формате 'Y-m-d'.

Michael Watson Michael Watson
23 авг. 2011 г. 15:49:57

Вы глобализируете $date или возвращаете её из функции? Можете также показать код этой функции?

Chip Bennett Chip Bennett
23 авг. 2011 г. 16:31:33

Ладно, я обновил исходный пост с дополнительными деталями. Я мог бы сделать date глобальной, но действительно ли это необходимо? Разве не лучше, если возможно, просто как-то передать её?

Michael Watson Michael Watson
23 авг. 2011 г. 16:42:11

Я обновил свой ответ. Нам просто нужно придумать способ определить ID записи, чтобы получить правильную дату для использования в запросе.

Chip Bennett Chip Bennett
23 авг. 2011 г. 20:58:51

Абсолютно верно. Я последовал вашему первоначальному совету и получаю ID записи со страницы через json, а затем просто глобализирую его. Что работает нормально, но я предполагаю, что это не лучшая практика? Сейчас все работает прекрасно, но я бы чувствовал себя гораздо лучше, если бы мог передавать эти данные приватно. Большое спасибо за вашу помощь до сих пор.

Michael Watson Michael Watson
24 авг. 2011 г. 13:16:09
Показать остальные 2 комментариев