Filtrar por un campo personalizado y ordenar por otro

17 feb 2011, 16:19:15
Vistas: 20.3K
Votos: 11

Tengo un tipo de post personalizado "Listing" y quiero obtener todos los Listings que tienen un campo personalizado gateway_value != 'Yes', y ordenar los resultados por otro campo personalizado, location_level1_value. Puedo hacer que las consultas funcionen por separado, pero no puedo combinarlas:

Consulta 1 (ordenar por ubicación):

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

Consulta 2 (valor del campo personalizado != Yes):

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

Consulta combinada:

Consulté el codex para obtener ayuda con esto, pero la siguiente consulta no funciona:

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

¿Qué estoy haciendo mal en la consulta combinada?

[ACTUALIZACIÓN]: Ahora que se ha lanzado la versión 3.1, la consulta combinada anterior todavía no funciona. Obtengo resultados, pero no están ordenados correctamente.

[ACTUALIZACIÓN]: var_dump($wp_query->request) muestra lo siguiente:
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
Comentarios

¿Estás usando WordPress 3.1? El parámetro meta_query es nuevo en la versión 3.1, que se lanzará muy pronto, pero la versión estable actual sigue siendo 3.0.5, sin este parámetro.

Jan Fabry Jan Fabry
17 feb 2011 17:08:25

Eh... cierto, probablemente esa sea la razón entonces. ¿Hay alguna forma de que funcione en 3.0.5?

gillespieza gillespieza
17 feb 2011 18:11:25

Miljenko tiene la mejor respuesta, deberías aceptar la suya en lugar de la tuya.

Hugo Hugo
3 abr 2012 08:24:38
Todas las respuestas a la pregunta 3
0

Podrías usar la consulta para filtrar el contenido como deseas utilizando 'meta_query' con opciones de filtrado, y para la parte del orden, simplemente añade/modifica los siguientes parámetros:

  • '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',            // esto significa que usaremos un campo meta  
                                               // seleccionado para ordenar
    
        'meta_key' => 'location_level1_value', // esto indica qué campo meta  
                                               // se usará en el ordenamiento,  
                                               // independientemente de los filtros
        'order'    => 'ASC',
        'paged'    => $paged
        )
    );
    
14 oct 2011 00:39:00
11

Como dijo Jan, en el nuevo WordPress 3.1 puedes usar meta_query, pero hasta que salga esa versión puedes usar tu primera consulta para ordenar y filtrar dentro de tu loop de esta manera:

 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();
              //haz tus operaciones del loop
} 

y agrega este código a tu functions.php

   //filtro de unión
         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;
            }
         }
         //filtro where
         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;
            }
         }

ahora esto debería funcionar.

17 feb 2011 18:12:57
Comentarios

Gracias por esto. Esto funciona, excepto que tengo este extraño efecto secundario de que mi paginación ya no funciona correctamente. En lugar de 9 por página, tengo "espacios vacíos" en mi cuadrícula donde estarían las entradas personalizadas que tienen gateway_value == "Yes" sin el condicional... ¿Alguna idea sobre cómo solucionar esto?

gillespieza gillespieza
17 feb 2011 18:53:40

sí, eso afectaría la paginación, así que supongo que la única solución sería una consulta SQL personalizada, dame unos minutos.

Bainternet Bainternet
17 feb 2011 19:10:27

No te preocupes - simplemente usaré la segunda consulta y usaré el plugin http://wordpress.org/extend/plugins/post-types-order hasta que se lance la versión 3.1 :)

gillespieza gillespieza
17 feb 2011 19:20:55

vaya, acabo de volver para ver tu comentario después de encontrar una solución. de todos modos, está aquí para futuros consultantes.

Bainternet Bainternet
17 feb 2011 20:01:31

@בניית אתרים - Si indentas todo tu código será más fácil pegarlo en las respuestas. Ej. Ponlo en tu editor preferido, selecciónalo todo, luego indéntalo una vez, ahora copia y pega, y evitarás tener que añadir 4 espacios antes de cada línea del código (todo debería quedar en un bloque de código perfectamente sin necesidad de ajustes manuales).

t31os t31os
17 feb 2011 20:18:37

@t31os - normalmente lo hago, pero no cuando respondo desde mi celular.

Bainternet Bainternet
17 feb 2011 20:20:38

¿Escribiste eso desde un teléfono?... ¡respeto!.. yo ni siquiera intentaría escribir código en un teléfono.. :) +1 por las habilidades con el móvil! ;)

t31os t31os
17 feb 2011 20:39:09

t31os: LOL, ¡el HTC Desire es genial!!

Bainternet Bainternet
17 feb 2011 20:40:23

He intentado pegar bloques de código con tabulaciones desde mi editor de texto y nunca funciona - siempre tengo que agregar los espacios manualmente

gillespieza gillespieza
17 feb 2011 23:07:48

Copiar y pegar desde notepad++ en firefox funciona bien.

Bainternet Bainternet
17 feb 2011 23:11:27

Probaré eso (actualmente usando PsPad y Chrome)

gillespieza gillespieza
19 feb 2011 20:37:23
Mostrar los 6 comentarios restantes
0

Disculpas por responder mi propia pregunta:

Al revisar [http://core.trac.wordpress.org/ticket/15031][1], parece que este es un problema conocido. Lo he solucionado (¿o hackeado?) para que funcione usando post_filter, de la siguiente manera (solo como referencia para cualquiera que esté buscando la misma respuesta):

En 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 modificado en el archivo de plantilla###

$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
    ));
24 feb 2011 00:38:17