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"

gillespieza
la source
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
        )
    );
Miljenko Barbir
la source
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.

Bainternet
la source
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
    ));
gillespieza
la source