web-dev-qa-db-ja.com

ドロップダウンを使用してカスタムフィールドで検索結果を並べ替える

私のsearch.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をつかんで追加することで現在の結果を日付順にソートしてから結果を含むページを再読み込みします---

// 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

ただし、現在はコードを使用して数値のカスタムフィールド(高から低、低から高)に基づいて並べ替えることで、コードをさらに改善しようとしています。

それは私が主題について見つけることができるすべての情報がそうすることのはるかに複雑な方法を持っているようです。私が既に始めたコードを使用してこれをする方法はありますか?

_アップデート_

近づいているようです -

私のsearch.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"と書かれているところ私のカスタムフィールドには名前を使います。

1
Rich

わかりました@Nicolaiの提案と、別の質問からの回答(私はリンクを失ったようです)を使ってそれを考え出しました。

まず第一に、私は自分の番号にコンマが含まれていないことを確認しなければなりませんでした。それがない場合は自分の投稿メタを保存してください。

それから私が別の質問で見つけたコード、私は使って、私の functions.php file - に入れました

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 ページで私は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>

これはトリックをしているようで、ページネーションで動作します、私が今持っている問題だけは -

  1. 醜いURL
  2. 投稿がソートされた状態でページが再ロードされると、ドロップダウン選択はデフォルト、つまりユーザーが選択したオプションの上にあるはずの「最新」に戻ります。
1
Rich

orderbyは例えばmeta_valueまたはmeta_value_num - さまざまな特定のmeta_typeが利用可能です - メタデータ順に並べ替えます。さらに、meta_keyを設定してクエリに含める必要があります。正確に、そして誤解を避けるために、meta_keyはソートしているフィールドのkeynameでなければなりません。詳細については、WP_Queryドキュメントの Order&Orderbyパラメータ および Custum Fieldsパラメータ のセクションを参照してください。

1
Nicolai

フォームを送信すると、フォームは自動的に選択値をURLに追加します。そのような値&orderby=date&order=dscを作成する必要はありません。単一の選択値で複数の情報を渡したい場合は、より単純な値とifステートメントを使用できます。最新のオプションのために私は値としてnewestを使い、そのような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を作成することを気にするべきではないと思います。パラメータの数が少ない場合はNice URLを作成したくなるかもしれませんが、アプリが大きくなって追加の書き換えケースとロジックを追加しても意味がありません。あなたが上司やクライアントにニースURLをあきらめるよう説得する必要がある場合は、検索ページでそれらをAmazonに表示してください。私はそれらをスペシャリストと見なしていますが、検索中にNice URLを使用しません。

以下のコードは、投稿をdateprice、およびsizeでソートする方法の完全に実用的な例です。ソートフォームを表示したい場所で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');
1
kierzniak