Filtrer par un champ personnalisé, commander par un autre?


10

J'ai un type de poste personnalisé « Liste » et je veux obtenir toutes les annonces qui ont un champ personnalisé gateway_value != 'Yes'et trier les résultats par un autre champ personnalisé, location_level1_value. Je peux faire fonctionner les requêtes séparément, mais je ne peux pas les combiner:

Requête 1 (trier par emplacement):

                $wp_query = new WP_Query( array (
                    'post_type' => 'listing',
                    'post_status' => 'publish',
                    'posts_per_page' => '9',
                    'meta_key' => 'location_level1_value',
                    'orderby' => 'location_level1_value',
                    'order' => 'ASC',
                    'paged' => $paged
                    )
                 );

Requête 2 (valeur de champ personnalisé! = Oui):

                $wp_query = new WP_Query( array (
                    'post_type' => 'listing',
                    'posts_per_page' => '9',
                    'post_status' => 'publish',
                    'meta_key' => 'gateway_value',
                    'meta_value' => 'Yes',
                    'meta_compare' => '!=',
                    'paged' => $paged
                    )
                );

Requête combinée:

J'ai regardé le codex pour obtenir de l'aide, mais la requête suivante ne fonctionne pas:

                $wp_query = new WP_Query( array (
                    'post_type' => 'listing',
                    'posts_per_page' => '9',
                    'post_status' => 'publish',
                    'meta_query' => array(
                        array(
                            'key' => 'gateway_value',
                            'value' => 'Yes',
                            'compare' => '!='
                        ),
                        array(
                            'key' => 'location_level1_value'
                        )
                    ),
                    'orderby' => "location_level1_value",
                    'order' => 'ASC',
                    'paged' => $paged
                    )
                );

Que fais-je de mal avec la requête combinée?

[MISE À JOUR]: Maintenant que la version 3.1 a été publiée, la requête combinée ci-dessus ne fonctionne toujours pas. J'obtiens des résultats, mais pas correctement triés.

[MISE À JOUR]: var_dump($wp_query->request)donne ce qui suit:
string(527) " SELECT SQL_CALC_FOUND_ROWS wp_7v1oev_posts.* FROM wp_7v1oev_posts INNER JOIN wp_7v1oev_postmeta ON (wp_7v1oev_posts.ID = wp_7v1oev_postmeta.post_id) INNER JOIN wp_7v1oev_postmeta AS mt1 ON (wp_7v1oev_posts.ID = mt1.post_id) WHERE 1=1 AND wp_7v1oev_posts.post_type = 'listing' AND (wp_7v1oev_posts.post_status = 'publish') AND wp_7v1oev_postmeta.meta_key = 'gateway_value' AND CAST(wp_7v1oev_postmeta.meta_value AS CHAR) != 'Yes' AND mt1.meta_key = 'location_level1_value' ORDER BY wp_7v1oev_posts.post_date DESC LIMIT 0, 9"


3
Utilisez-vous WordPress 3.1? Le meta_queryparamètre est nouveau en 3.1, et devrait être publié très bientôt, mais la version stable actuelle est toujours 3.0.5, sans ce paramètre.
— Jan Fabry

Euh ... à droite, ce serait probablement pourquoi alors. Est-il possible de le faire fonctionner en 3.0.5?
— gillespieza

Miljenko a la meilleure réponse que vous devriez accepter la sienne au lieu de la vôtre.
— Hugo

Réponses:


9

Vous pouvez utiliser la requête pour filtrer le contenu comme vous le souhaitez en utilisant la 'meta_query' avec des options de filtrage, et pour la partie commande, ajoutez / modifiez simplement les paramètres suivants:

  • 'orderby' => 'meta_value'
  • 'meta_key' => 'location_level1_value'
  • 'order' => 'ASC'

    $wp_query = new WP_Query( array (
        'post_type'      => 'listing',
        'posts_per_page' => '9',
        'post_status'    => 'publish',
        'meta_query'     => array(
            array(
                'key'       => 'gateway_value',
                'value'     => 'Yes',
                'compare'   => '!='
            )
        ),
        'orderby'  => 'meta_value',            // this means we will be using a selected 
                                               // meta field to order
    
        'meta_key' => 'location_level1_value', // this states which meta field 
                                               // will be used in the ordering, 
                                               // regardless of the filters
        'order'    => 'ASC',
        'paged'    => $paged
        )
    );

2

Tout comme Jan l'a dit dans le nouveau WordPress 3.1, vous pouvez utiliser, meta_querymais jusqu'à ce que cela sorte, vous pouvez utiliser votre première requête pour commander et filtrer à l'intérieur de votre boucle comme suit:

 Global $my_query;
$my_query = new WP_Query( array (
                    'post_type' => 'listing',
                    'post_status' => 'publish',
                    'posts_per_page' => '9',
                    'meta_key' => 'location_level1_value',
                    'orderby' => 'location_level1_value',
                    'order' => 'ASC',
                    'paged' => $paged
                    )
                 );
while ($my_query->have_posts){
    $my_query->the_post();
              //do your loop stuff
} 

et ajoutez ce code à vos fonctions.php

   //join filter
         add_filter('posts_join', 'listing_join_865' );
         function listing_join_865($join){
Global$ my_query;            
if ('listing' = $my_query->query['post_type']){
                $restriction1 = 'gateway_value';
                return $join .="
                LEFT JOIN $wpdb->postmeta AS $restriction1 ON(
                $wpdb->posts.ID = $restriction1.post_id
                AND $restriction1.meta_key = '$restriction1'
                )";
             }else {
                return $join;
            }
         }
         //where filter
         add_filter('posts_where', 'listing_where_865' );
         function listing_where_865($where){
             global $my_query;
            if ('listing' = $my_query->query['post_type']){
                return $where.= " AND $restriction1.meta_value != 'yes'";
            }else{
                return $where;
            }
         }

maintenant cela devrait fonctionner.


Merci pour cela. Cela fonctionne, sauf que j'ai cet effet secondaire étrange que ma pagination ne fonctionne plus correctement. Au lieu de 9 par page, j'ai des "espaces vides" dans ma grille où les messages personnalisés qui gateway_value == "Yes"auraient été sans condition ... Une idée sur la façon de résoudre ce problème?
— gillespieza

oui, ce serait gâcher la pagination, donc je suppose que le seul moyen de contourner ce problème serait une requête SQL personnalisée, donnez-moi quelques minutes.
— Bainternet

Ne vous inquiétez pas - je vais simplement utiliser la deuxième requête et utiliser le plugin wordpress.org/extend/plugins/post-types-order jusqu'à la sortie de la version 3.1 :)
— gillespieza

dam, je suis revenu tout à l'heure pour voir votre commentaire après avoir trouvé une solution. de toute façon, il est là pour les futurs demandeurs.
— Bainternet

1
@ t31os - je le fais habituellement, mais pas lorsque je réponds depuis mon téléphone portable.
— Bainternet

1

Toutes mes excuses pour avoir répondu à ma propre question:

Il semble que ce problème soit connu en consultant [http://core.trac.wordpress.org/ticket/15031[-021]. Je l'ai corrigé (piraté?) Pour qu'il fonctionne en utilisant post_filter, comme ça (juste pour la référence de quelqu'un qui pourrait chercher la même réponse):

Dans functions.php ###

add_filter('posts_orderby', 'EV_locationl1' );
function EV_locationl1 ($orderby) {
    global $EV_locationl1_orderby;
    if ($EV_locationl1_orderby) $orderby = $EV_locationl1_orderby;
    return $orderby;
}

Wp_query modifié dans le fichier modèle ###

$EV_locationl1_orderby = " mt1.meta_value ASC";

$wp_query = new WP_Query( array (
    'post_type' => 'listing',
    'posts_per_page' => '9',
    'post_status' => 'publish',
    'meta_query' => array(
            array(
                    'key' => 'gateway_value',
                    'value' => 'Yes',
                    'compare' => '!='
                    ),
            array(
                    'key' => 'location_level1_value'
            )
        ),
    'order' => $EV_locationl1_orderby,
    'paged' => $paged
    ));
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.