Как можно установить `posts_per_page` в WP с выпадающим списком BS4, используя URL? - PullRequest
1 голос
/ 11 июля 2019

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

Я видел более старый пост в стеке здесь , но $showposts устарел, и теперь у нас также есть фильтр pre_get_posts. Который, я думал, мог бы выполнять работу по мере необходимости.

Вопрос:

Каков наилучший способ передачи моих якорей атрибут данных в WP, posts_per_page параметр с использованием pre_get_posts фильтра или нет?


РЕДАКТИРОВАТЬ: 13 ИЮЛЬ 22: 47

Вот что у меня есть:

<div class="btn-group">
  <button class="btn btn-sm dropdown-toggle px-0 mr-3" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    Show:
  </button>
  <div class="dropdown-menu">
    <a class="dropdown-item active" href="javascript:;" data-handle="display" data-value="15">15 items per page</a>
    <a class="dropdown-item" href="javascript:;" data-handle="display" data-value="30">30 items per page</a>
    <a class="dropdown-item" href="javascript:;" data-handle="display" data-value="45">45 items per page</a>
    <a class="dropdown-item" href="javascript:;" data-handle="display" data-value="60">60 items per page</a>
  </div>
</div>

Мой фильтр functions.php

// . Custom Search for Catalogue items
// . =================================
function catalogue_search( $query ) {

    if (isset($_GET['display'])) {
        $selValue = $_GET['display'];
    } else {
        $selValue = 15;
    }

    if ( $query->is_search() && 'products' === $query->get( 'post_type' ) ) {
        $query->set( 'posts_per_page', $selValue );
    }
}
add_action( 'pre_get_posts', 'catalogue_search' );

Мой JQ.

$("document").ready(function() {

  sortBy = null;
  display = null;

  setTimeout(function() {

    if ($(".dropdown-menu a").data('handle') == 'sort_by') {
      sortBy = '&' + $(this).data('handle') + '=' + $(this).data('value');
    }

    if ($(".dropdown-menu a").data('handle') == 'display') {
      display = '&' + $(this).data('handle') + '=' + $(this).data('value');
    }

    $('.btn-group').find('.active').trigger('click');

  }, 10);

  $(".dropdown-menu a").click(function() {

    if ($(this).data('handle') == 'sort_by') {
      sortBy = '&' + $(this).data('handle') + '=' + $(this).data('value');
    }

    if ($(this).data('handle') == 'display') {
      display = '&' + $(this).data('handle') + '=' + $(this).data('value');
    }

    $(this).closest('.btn-group').find(".dropdown-menu a").removeClass('active');
    $(this).addClass('active');    

    $(this).closest('.btn-group').find('.appended').remove();
    $(this).closest('.btn-group').find('button').append('<span class="appended">' + $(this).text() + '</span>'); 

    window.location.hash = sortBy + display;    

  });

});

Этот JS Fiddle должен дать вам рабочий пример моих текущих выпадений BS4.

ПРИМЕЧАНИЕ:

С новым JS согласно предложению @ Chris мой URL теперь читается как таковой; domain.com/?s=&post_type=products&submit=#&sort_by=recent&display=15

Я подумал, что это проблема $GET, но я не уверен, как ее решить ...

var_dump($_GET); отображает следующее;

array(3) { 
    ["s"]=> string(0) "" 
    ["post_type"]=> string(8) "products" 
    ["submit"]=> string(0) "" 
}

Должен отобразиться;

array(3) { 
    ["s"]=> string(0) "" 
    ["post_type"]=> string(8) "products" 
    ["submit"]=> string(0) ""
    ["display"]=> string(0) "" 
}

Имея это в виду, я добавил;

// . Add Query Vars
// . =======================
function add_query_vars_filter( $vars ) {
  $vars[] = 'display';
  return $vars;
}
add_filter( 'query_vars', 'add_query_vars_filter' );

Проблема все еще сохраняется. : /

1 Ответ

1 голос
/ 12 июля 2019

Вы на правильном пути. Из того, что я вижу, вы пытаетесь отправить выбранную пользователем опцию через AJAX. Однако фильтр pre_get_posts используется для фильтрации запроса WordPress по умолчанию. Поскольку вы отправляете через AJAX, WP не собирается выполнять какие-либо запросы по умолчанию, поэтому pre_get_posts здесь в основном бесполезен.

У вас действительно есть два варианта,

  1. Кювет AJAX. В этом случае вместо отправки выбранной опции на сервер асинхронно, вы можете добавить ее в URL. Поэтому, если пользователь находится на domain.com/blog, после выбора параметра вы можете перенаправить пользователя на тот же URL-адрес, добавив параметр в виде строки запроса.
$(".dropdown-menu a").click(function() {

    //get value
    //...

    //redirect
    window.location = 'domain.com/blog?posts_per_page=' + value;

});

WordPress может получить эту строку запроса и обработать логику запроса. Если нет, вы можете прослушать это значение (или пользовательское значение), а затем использовать pre_get_posts для фильтрации.

//
function customize_query_params( $query ) {

    //only if our customization query var is set
    if( ! isset( $_GET['display'] ) )
        return $query;

    //never trust the user
    $display = filter_var( $_GET['display'], FILTER_SANITIZE_NUMBER_INT );

    //if $display != something we want, change it to be safe

    //customize the query
    $query->set('posts_per_page', $display);

    //
    return $query;
}

add_action('pre_get_posts', 'customize_query_params');

Это также должно хорошо работать с нумерацией страниц, так как параметры страницы также передаются в WP в URL.

  1. Другой вариант - придерживаться AJAX. Во-первых, вам нужно убедиться, что вы правильно регистрируете свои обработчики AJAX в WP. Я бы взглянул на документы здесь . После того, как вы правильно зарегистрируете свой обработчик AJAX, вы можете выполнить запрос самостоятельно и вернуть результаты в интерфейс.
add_action( 'wp_ajax_custom_action', 'filter_by_user_option' );
add_action( 'wp_ajax_nopriv_custom_action', 'filter_by_user_option' );

function filter_by_user_option() {

    //get the value you submitted
    $limit = filter_var( $_POST['attribute'], FILTER_SANITIZE_NUMBER_INT );

    //get posts
    $posts = get_posts([
        'post_type' => 'post',
        'post_status' => 'publish',
        'posts_per_page' => $limit,
        'paged' => 1
    ]);

    //return a response to the frontend. You could output JSON, or raw HTML
    header("Content-type: application/json");
    die( json_encode($posts) );

}

//front end
$(".dropdown-menu a").click(function() {

    //get value
    //...

    //redirect
    $.ajax({
        type: 'post',
        url: '<?php echo admin_url(‘admin-ajax.php’) ?>',
        data: {
            action: 'custom_action',
            attribute: value
        },
        success: function(res) {

            //res = array of posts. do something with this

        }
    });

});

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

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...