使用下拉菜单按自定义字段对搜索结果进行排序

时间:2017-12-14 作者:730wavy

在我的搜索中。php页面,我有一个“排序方式”下拉列表,它几乎完全符合我的要求--

<select class="dropdown-class" name="sort-posts" id="sortbox" onchange="document.location.href=location.href+this.options[this.selectedIndex].value;">
<option disabled>Sort by</option>
<option value="&orderby=date&order=dsc">Newest</option>
<option value="&orderby=date&order=asc">Oldest</option>
</select>

<script type="text/javascript">

    <?php if (( $_GET[\'orderby\'] == \'date\') && ( $_GET[\'order\'] == \'dsc\')) { ?>
        document.getElementById(\'sortbox\').value=\'orderby=date&order=dsc\';

    <?php } elseif (( $_GET[\'orderby\'] == \'date\') && ( $_GET[\'order\'] == \'asc\')) { ?>
        document.getElementById(\'sortbox\').value=\'orderby=date&order=asc\';

    <?php } else { ?>
        document.getElementById(\'sortbox\').value=\'orderby=date&order=desc\';

    <?php } ?>

</script>
当Im出现在搜索结果页面上时,排序下拉列表将根据日期对当前结果进行排序,方法是抓取url并附加到url,然后用结果重新加载页面---

// Before
mydomain.com/?s=Search&property_city=new-york-city&beds=Any 

// After
mydomain.com/?s=Search&property_city=new-york-city&beds=Any&orderby=date&order=dsc
然而,我现在正试图进一步改进代码,使用它根据数字自定义字段(从高到低和从低到高)进行排序。

似乎我能找到的关于这个主题的所有信息都有更复杂的方法。是否有必要使用我已经开始使用的代码来执行此操作?

UPDATE

我好像越来越近了-

在我的搜索中。php页面我的循环之前有这个----

<select class="dropdown-class" name="sort-posts" id="sortbox" onchange="document.location.href=location.href+this.options[this.selectedIndex].value;">
<option disabled>Sort by</option>
<option value="&orderby=date&order=dsc">Newest</option>
<option value="&orderby=date&order=asc">Oldest</option>
<option value="&orderby=property_price&order=asc">Most Expensive</option>
<option value="&orderby=property_price&order=dsc">Least Expensive</option>
<option value="&orderby=property_area&order=dsc">Largest</option>
<option value="&orderby=property_area&order=asc">Smallest</option>
</select>

<script type="text/javascript">

    <?php if (( $_GET[\'orderby\'] == \'date\') && ( $_GET[\'order\'] == \'dsc\')) { ?>
        document.getElementById(\'sortbox\').value=\'orderby=date&order=dsc\';

    <?php } elseif (( $_GET[\'orderby\'] == \'date\') && ( $_GET[\'order\'] == \'asc\')) { ?>
        document.getElementById(\'sortbox\').value=\'orderby=date&order=asc\';

    <?php } elseif (( $_GET[\'orderby\'] == \'property_price\') && ( $_GET[\'order\'] == \'asc\')) { ?>
        document.getElementById(\'sortbox\').value=\'orderby=property_price&order=asc\';

        <?php } elseif (( $_GET[\'orderby\'] == \'property_price\') && ( $_GET[\'order\'] == \'dsc\')) { ?>
        document.getElementById(\'sortbox\').value=\'orderby=property_price&order=dsc\';

    <?php } elseif (( $_GET[\'orderby\'] == \'property_area\') && ( $_GET[\'order\'] == \'asc\')) { ?>
        document.getElementById(\'sortbox\').value=\'orderby=property_area&order=asc\';

        <?php } elseif (( $_GET[\'orderby\'] == \'property_area\') && ( $_GET[\'order\'] == \'dsc\')) { ?>
        document.getElementById(\'sortbox\').value=\'orderby=property_area&order=dsc\';


    <?php } else { ?>
        document.getElementById(\'sortbox\').value=\'orderby=date&order=desc\';

    <?php } ?>

</script>
其中显示“orderby=xxx”,我只使用我的名称作为自定义字段。

4 个回复
最合适的回答,由SO网友:730wavy 整理而成

好的,我用@Nicolai的建议和另一个问题的答案(我似乎已经失去了链接)解决了这个问题。

首先,我必须确保我的数字中没有逗号,我已经通过保存我的帖子元来做到了这一点。

然后我在另一个问题中找到的代码,我使用并放入functions.php 文件--

function wpse139657_orderby(){
    if( isset($_GET[\'orderby\']) ){
        $order = $_GET[\'order\'] or \'DESC\';
        set_query_var(\'orderby\', \'meta_value_num\');
        //set_query_var(\'meta_type\', \'numeric\');
        set_query_var(\'meta_key\', $_GET[\'orderby\']);
        set_query_var(\'order\', $order);
    }
}

add_filter(\'pre_get_posts\',\'wpse139657_orderby\');
然后在我的search.php 第I页在select下拉列表中使用了以下代码--

<select class="dropdown-class" name="sort-posts" id="sortbox" onchange="document.location.href=location.href+this.options[this.selectedIndex].value;">
<option disabled>Sort by</option>
<option value="&orderby=date&order=dsc">Newest</option>
<option value="&orderby=date&order=asc">Oldest</option>
<option value="&orderby=property_price2&order=DESC">Most Expensive</option>
<option value="&orderby=property_price2&order=ASC">Least Expensive</option>
<option value="&orderby=area2&order=DESC">Largest</option>
<option value="&orderby=area2&order=ASC">Smallest</option>
</select>
这似乎可以解决分页问题,我现在唯一的问题是--

当页面重新加载已排序的帖子时,下拉选择将返回到默认的ie“最新”,此时它仍应位于用户选择的选项上

SO网友:Nicolai Grossherr

orderby 应为,例如。meta_valuemeta_value_num – 各种特定meta_type\'可按元数据订购。另外ameta_key 必须设置并显示在查询中。准确地说,为了避免误解,meta_key 必须是keyname 要排序的字段的。仔细查看Order & Orderby ParametersCustum Fields Parameters 第节WP_Query 有关详细信息,请参阅文档。

SO网友:kierzniak

当您提交表单时,表单会自动将您的选择值添加到url。没有必要创造这样的价值&orderby=date&order=dsc. 若要在单个select值中传递多个信息,可以使用更简单的value和If语句。对于最新选项,我将使用newest as value和add做这样一个if语句。

// Url /?s=test&order=newest

$orderby = \'\';
$order = \'\';

// Get filtered $_GET[\'order\'] parameter
$value = filter_input( INPUT_GET, \'order\', FILTER_SANITIZE_STRING );

if( $value === \'newest\' ) {
    $orderby = \'date\';
    $order = \'desc\';
}

// Modify query using $orderby and $order parameters
使用JavaScript为我选择选项也是个坏主意。你应该检查电流order 参数并将选定属性添加到选项中。

// Url /?s=test&order=newest

// Get filtered $_GET[\'order\'] parameter
$value = filter_input( INPUT_GET, \'order\', FILTER_SANITIZE_STRING );
$selected = ($value === \'newest\') ? \'selected\': \'\' ;
?>

<select name="order">
    <option value="newest" <?php echo esc_attr( $selected ); ?>></option>
</select>
我认为你不应该费心制作好的url。对于少量的参数来说,创建一个好的url可能很有诱惑力,但当你的应用程序越来越大时,添加额外的重写用例和逻辑是没有目的的。如果你不得不说服你的老板或客户放弃好的URL,请在搜索页面上向他们展示亚马逊。我将他们视为专家,他们在搜索过程中不会使用好的URL。

下面的代码是如何按邮件排序的完整示例date, pricesize. 处决wpse_288655_display_form 要在其中显示排序表单的函数。

/**
 * Display sort form
 */
function wpse_288655_display_form() {

    /**
     * Get all params from url which are not part of our sort form
     * and display it in form as hidden inputs.
     */
    $search_param = filter_input( INPUT_GET, \'s\', FILTER_SANITIZE_STRING );

    /**
     * Current order value to select proper field
     */
    $value = filter_input( INPUT_GET, \'order\', FILTER_SANITIZE_STRING );
    ?>

    <form method="get">
        <?php wpse_288655_display_select(\'order\', \'Sort by:\', wpse_288655_get_order_by_options(), $value ); ?>

        <?php
            /**
             * Display all params from url which do not apply to our sort form
             */
        ?>
        <input type="hidden" name="s" value="<?php esc_attr_e( $search_param ); ?>">

        <button type="submit"><?php esc_html_e(\'Sort\'); ?></button>
    </form>
    <?php
}

/**
 * Get sort options
 */
function wpse_288655_get_order_by_options(){

    return array(
        \'\' => \'\',
        \'newest\' => __(\'Newest\'),
        \'oldest\' => __(\'Oldest\'),
        \'most_expensive\' => __(\'Most Expensive\'),
        \'least_expensive\' => __(\'Least Expensive\'),
        \'largest\' => __(\'Largest\'),
        \'smallest\' => __(\'Smallest\'),
    );
}

/**
 * Display select field
 */
function wpse_288655_display_select( $name, $label, $options, $value = \'\' ) {
    ?>
    <label><?php esc_html_e( $label ) ?></label>
    <select name="<?php esc_attr_e( $name ) ?>">
        <?php wpse_288655_display_options( $options, $value ); ?>
    </select>
    <?php
}

/**
 * Display select options
 */
function wpse_288655_display_options( $options, $value ) {

    foreach( $options as $option_value => $option_label ):
        $selected = ( $option_value === $value ) ? \' selected\' : \'\';
        ?>
        <option value="<?php esc_attr_e( $option_value ) ?>"<?php esc_attr_e( $selected ) ?>><?php esc_html_e( $option_label ) ?></option>
        <?php

    endforeach;
}

/**
 * Sort posts using pre_get_posts filter
 */
function wpse_288655_order_posts( $query ) {

    /**
     * Execute query only when we are on search page and this is main query
     */
    if ( $query->is_search() && $query->is_main_query() ) {

        $value = filter_input( INPUT_GET, \'order\', FILTER_SANITIZE_STRING );
        $order_by_options = wpse_288655_get_order_by_options();

        if( isset( $order_by_options[ $value ] ) && !empty( $value ) ) {

            switch( $value ) {
                case \'newest\':

                    $query->set( \'order\', \'desc\' );
                    $query->set( \'orderby\', \'date\' );

                    break;

                case \'oldest\':

                    $query->set( \'order\', \'asc\' );
                    $query->set( \'orderby\', \'date\' );

                    break;
                case \'most_expensive\':

                    $query->set( \'meta_key\', \'price\' ); // Your custom meta_key

                    $query->set( \'order\', \'desc\' );
                    $query->set( \'orderby\', \'meta_value_num\' );

                    break;
                case \'least_expensive\':

                    $query->set( \'meta_key\', \'price\' ); // Your custom meta_key

                    $query->set( \'order\', \'asc\' );
                    $query->set( \'orderby\', \'meta_value_num\' );

                    break;
                case \'largest\':

                    $query->set( \'meta_key\', \'size\' ); // Your custom meta_key

                    $query->set( \'order\', \'desc\' );
                    $query->set( \'orderby\', \'meta_value_num\' );

                    break;
                case \'smallest\':

                    $query->set( \'meta_key\', \'size\' ); // Your custom meta_key

                    $query->set( \'order\', \'asc\' );
                    $query->set( \'orderby\', \'meta_value_num\' );

                    break;
                default:
                    break;
            }
        }
    }
}

add_filter(\'pre_get_posts\', \'wpse_288655_order_posts\');

SO网友:Misha Rudrastyh

因为下面的答案看起来很不确定-例如,你不能仅仅挂钩pre_get_posts 因为它会影响网站上的每个查询,甚至在WordPress管理区域。

我给您的第一个建议是拒绝使用JavaScript,我希望您的下拉列表如下所示:

<form action="" method="GET"><select name="sortposts">
    <option disabled>Sort by</option>
    <option value="date-DESC">Newest</option>
    <option value="date-ASC">Oldest</option>
    <option value="property_price-ASC">Most Expensive</option>
    <option value="property_price-DESC">Least Expensive</option>
.....
太好了,现在也一样search.php 文件您可以执行以下操作:

<?php
    global $wp_query;

    // let\'s create new array with args
    if( !empty( $_GET[\'sortposts\'] ) ) {
        // I recommend to explode it because we\'re take 2 param values from one $_GET variable
        $sort_args = explode( "-", $_GET[\'sortposts\'] );
        // $sort_args[0] is what we sort
        // $sort_args[1] is how we sort - Ascending or Descending
        $new_args[\'order\'] = $sort_args[1];
        if( $sort_args[0] == \'date\' ) {
            // date is a default WP_Query value, so we do nothing
            $new_args[\'orderby\'] == \'date\';
        } elseif( $sort_args[0] == \'property_price\' ) {
            $new_args[\'orderby\'] = \'meta_value_num\';
            $new_args[\'meta_key\'] = \'THIS IS A PROPERTY PRICE META KEY\';
        }
    }

    $args = array_merge( $wp_query->query_vars, $new_args );
    query_posts( $args );
像这样的。但如果您愿意,当然可以使用pre\\u get\\u posts。只要在那里添加条件,过滤器就不会在不相关的页面上启动。

如果您想用AJAX实现过滤,也可以看看本教程https://rudrastyh.com/wordpress/ajax-load-more-with-filters.html

结束

相关推荐

Query posts using less than

我有一个工作查询,使用pre_get_posts 使用status post格式,仅在使用UNIX时间戳的日期范围内显示这些帖子。唯一的问题是,即使帖子超出范围,它仍然会被查询。我只是想知道是否有更好的方法使用自定义字段查询帖子,该字段使用的代码:$args = array(\'status_message\' => \'alerts\'); $status_alert = new WP_Query( $args ); $notice_startend = false; $n