Filtrare după un câmp personalizat, ordonare după altul?
Am un tip de postare personalizat "Listing" și vreau să obțin toate Listările care au un câmp personalizat gateway_value != 'Yes' și să ordonez rezultatele după un alt câmp personalizat, location_level1_value. Pot face interogările să funcționeze separat, dar nu le pot combina:
Interogarea 1 (sortare după locație):
$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
)
);
Interogarea 2 (valoarea câmpului personalizat != 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
)
);
Interogare combinată:
M-am uitat în codex pentru ajutor cu aceasta, dar următoarea interogare nu funcționează:
$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
)
);
Ce fac greșit în interogarea combinată?
[ACTUALIZARE]: Acum că versiunea 3.1 a fost lansată, interogarea combinată de mai sus tot nu funcționează. Primesc rezultate, doar că nu sunt sortate corect.
[ACTUALIZARE]: var_dump($wp_query->request) returnează următoarele:
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"
Puteți utiliza interogarea pentru a filtra conținutul conform intenției dumneavoastră folosind 'meta_query' cu opțiuni de filtrare, iar pentru partea de ordonare, adăugați/modificați următorii parametri:
- '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' => 'Da', 'compare' => '!=' ) ), 'orderby' => 'meta_value', // aceasta înseamnă că vom folosi un câmp meta // selectat pentru ordonare 'meta_key' => 'location_level1_value', // acesta specifică care câmp meta // va fi utilizat în ordonare, // indiferent de filtre 'order' => 'ASC', 'paged' => $paged ) );
Exact cum a menționat Jan în noul WordPress 3.1, poți folosi meta_query, dar până când acea versiune va fi lansată, poți utiliza prima ta interogare pentru a ordona și filtra în interiorul loop-ului tău, astfel:
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();
//fă ce ai nevoie în loop
}
și adaugă acest cod în functions.php
//filtru de join
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;
}
}
//filtru de 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;
}
}
Acum ar trebui să funcționeze.
Mulțumesc pentru asta. Funcționează, cu excepția unui efect secundar ciudat: paginarea mea nu mai funcționează corect. În loc de 9 pe pagină, am "spații goale" în grila mea unde ar fi fost postările personalizate care au gateway_value == "Yes" fără condiția... Ai vreo idee cum să rezolv asta?
gillespieza
da, asta ar strica paginarea, așa că presupun că singura soluție ar fi o interogare SQL personalizată, dă-mi câteva minute.
Bainternet
Nu-ți face griji - voi folosi doar a doua interogare și voi folosi plugin-ul http://wordpress.org/extend/plugins/post-types-order până când va fi lansată versiunea 3.1 :)
gillespieza
la naiba, tocmai m-am întors acum să văd comentariul tău după ce am găsit o soluție. oricum, este aici pentru cei care vor întreba în viitor.
Bainternet
@בניית אתרים - Dacă indentați tot codul, va fi mai ușor să-l lipiți în răspunsuri. Ex. Puneți-l în editorul ales, selectați tot, apoi indentați-l o dată, acum copiați și lipiți și veți evita nevoia de a adăuga 4 spații înaintea oricărei linii de cod (ar trebui să intre frumos într-un bloc de cod fără să fie nevoie să vă jucați cu el).
t31os
@t31os - de obicei fac asta, dar nu când răspund de pe telefonul meu mobil.
Bainternet
Ai scris asta de pe un telefon... respect!.. nici nu aș încerca să scriu cod pe un telefon.. :) +1 pentru skillz-urile pe telefon! ;)
t31os
Am încercat să lipesc blocuri de cod tabulate din editorul meu de text și nu funcționează niciodată - întotdeauna trebuie să adaug spații manual
gillespieza
Copierea și lipirea din Notepad++ în Firefox funcționează fără probleme.
Bainternet
Scuze că răspund la propria întrebare:
Uitându-mă la [http://core.trac.wordpress.org/ticket/15031][1], se pare că aceasta este o problemă cunoscută. Am rezolvat (sau mai degrabă am făcut un hack) să funcționeze folosind post_filter, astfel (pentru oricine care caută același răspuns):
În 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;
}
Modificat wp_query în fișierul template###
$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
));