web-dev-qa-db-fra.com

trier les résultats de la recherche par champs personnalisés à l'aide de la liste déroulante

Sur ma page search.php, j'ai un menu déroulant "Trier par" qui fonctionne presque exactement comme je le veux -

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

Lorsque je suis sur la page de résultats de recherche, la liste déroulante trie les résultats actuels en fonction de la date en saisissant l'URL et en l'ajoutant, puis en rechargeant la page avec les résultats ---

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

Cependant, j'essaie maintenant d'améliorer encore le code en l'utilisant pour trier sur la base de champs personnalisés numériques (de haut en bas et de bas en haut).

Il semble que toutes les informations que je peux trouver sur le sujet ont des façons beaucoup plus compliquées de le faire. Est-il possible de le faire en utilisant le code sur lequel j'ai déjà commencé?

METTRE À JOUR

Je semble me rapprocher -

Sur ma page search.php j'ai ceci avant ma boucle ----

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

où il est écrit "orderby = xxx" J'utilise simplement mes noms pour mes champs personnalisés.

1
Rich

Ok, j'ai compris à l'aide de la suggestion de @Nicolai et d'une réponse à une autre question (à laquelle il semble que j'ai perdu le lien).

Pour commencer, je devais m'assurer que mes numéros ne contenaient aucune virgule, ce que j'avais déjà fait en enregistrant mon méta de messages sans le méta.

Ensuite, le code que j'ai trouvé dans une autre question, j'ai utilisé et placé dans mon functions.php fichier -

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');

Puis sur ma search.php page, j’ai utilisé le code suivant pour le menu déroulant de sélection -

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

Cela semble faire l'affaire et fonctionne avec la pagination, les seuls problèmes que j'ai actuellement sont -

  1. Urls laids
  2. Lorsque la page est rechargée avec les articles triés, la liste déroulante revient à la valeur par défaut, c.-à-d. "Le plus récent", alors que l'option choisie doit toujours l'être.
1
Rich

orderby devrait être par exemple meta_value ou meta_value_num - divers meta_type spécifiques sont disponibles - à commander par métadonnées. De plus, un meta_key doit être défini et présent dans la requête. Pour être précis et éviter les malentendus, meta_key doit être la keyname du champ que vous triez. Examinez de plus près les paramètres Order & Orderby et Custum Fields Parameters de la documentation WP_Query pour plus d'informations.

1
Nicolai

Le formulaire ajoutera automatiquement votre valeur de sélection à l'URL lorsque vous soumettez le formulaire. Il n'est pas nécessaire de créer une telle valeur &orderby=date&order=dsc. Si vous souhaitez transmettre plusieurs informations dans une valeur de sélection unique, vous pouvez utiliser une valeur plus simple et une instruction if. Pour l’option la plus récente, j’utiliserais newest comme valeur et ajouterais une telle instruction 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

Utiliser JavaScript pour choisir une option pour moi est également une mauvaise idée. Vous devriez vérifier le paramètre actuel order et ajouter l'attribut sélectionné à votre option.

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

Je pense que vous ne devriez pas vous embêter à faire de Nice url. Pour un petit nombre de paramètres, il peut être tentant de créer une URL agréable, mais lorsque votre application s'agrandit, elle ajoute une casse de réécriture et une logique sans but. Si vous devez convaincre votre patron ou votre client d'abandonner les bonnes URL, montrez-leur Amazon sur la page de recherche. Je les considère comme des spécialistes et ils n'utilisent pas les URL de Nice lors de la recherche.

Le code ci-dessous illustre parfaitement comment trier les articles par date, price et size. Exécutez la fonction wpse_288655_display_form à l'endroit où vous souhaitez afficher le formulaire de tri.

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