Utilizarea împreună a parametrilor post__in și post__not_in?

2 aug. 2013, 05:13:30
Vizualizări: 22.6K
Voturi: 1

Încerc să afișez doar postările pe care un utilizator nu le-a văzut, astfel:

$exclude = array(1,2,3);
$include = array(3,4,5);
$args = array(
  'post_type'           => 'post',
  'post_status'         => 'publish',
  'posts_per_page'      => 30,
  'post__in'            => $include,
  'post__not_in'        => $exclude,
  'orderby'             => 'post__in',            
  'tax_query'           => array(
        'relation' => 'AND',
         array(
            'taxonomy'  => 'category',
            'field'     => 'slug',
            'terms'     => array($category_names),
            'operator'  => 'IN'
         ),
         array(
            'taxonomy'  => 'category',
            'field'     => 'ID',
            'terms'     => array($category_ids),
            'operator'  => 'NOT IN'
         )
  )
);
$posts = get_posts($args);

M-aș aștepta ca aceasta să returneze postările 4 și 5, dar returnează 3, 4 și 5.

Cum pot seta care parametru are prioritate între 'post__in' și 'post__not_in'?

Știu că aș putea folosi array_diff() pe variabilele $exclude și $include, dar realitatea este mai complicată decât această întrebare. Am multe array-uri diferite de comparat, și unele dintre ele sunt multidimensionale. De asemenea, includ și exclud anumite taxonomii.

Cred că este mai ușor pentru alții să citească dacă este un WP_Query sau o interogare $wpdb, decât rânduri și rânduri de PHP pentru a ajunge la un parametru de interogare.

De asemenea, dacă array_diff este egal cu un array gol, atunci interogarea returnează de fapt postări, nu nimic.

Așadar, poate cea mai bună cale este o interogare $wpdb, sau o modalitate de a utiliza meta_query din WP_Query pe câmpul ID al postării?

4
Comentarii

Poți să explici, te rog, realitatea complicată?

s_ha_dum s_ha_dum
2 aug. 2013 06:13:38

Actualizat pentru a explica de ce nu doresc să folosesc array_diff dacă este posibil. Cred că o abordare cu $wpdb ar putea fi cea mai bună.

Drew Baker Drew Baker
2 aug. 2013 08:22:19

@DrewBaker Încă nu înțeleg un lucru. Spui: Am multe array-uri diferite de comparat, iar unele dintre ele sunt multidimensionale Dar pentru a folosi include și exclude trebuie să transmiți un array simplu de id-uri. Deci faci vreo logică pentru a extrage două array-uri simple din array-ul diferit și multidimensional? Dacă da, poți de fapt să rulezi array_diff și dacă rezultatul este gol poți folosi un if și să nu rulezi niciodată query-ul, $posts = ! empty($diff) ? get_posts($args) : array();

gmazzap gmazzap
2 aug. 2013 12:40:56

OK, am înțeles ce spuneți. Voi folosi array_diff(). Mulțumesc!

Drew Baker Drew Baker
2 aug. 2013 20:18:19
Toate răspunsurile la întrebare 2
2

post__in și post__not_in se exclud reciproc.

Notă: nu poți combina post__in și post__not_in în aceeași interogare.

http://codex.wordpress.org/Class_Reference/WP_Query

După cum este formulată întrebarea ta, soluția pe care o respingi – cea de a folosi array_diff – este răspunsul evident.

Dacă este adevărat că acea soluție nu funcționează, vei avea nevoie de un filtru pe posts_where (probabil) care să ofere logica necesară interogării. Întrucât nu ai explicat "realitatea [care] este mai complicată decât această întrebare", nu este posibil să oferim o sugestie despre care ar putea fi acea logică.

Dar iată un exemplu de filtru posts_where:

function smbd_cats_by_days ($where = '') {
    // global $days_limit; // dacă este o variabilă
    // $days_limit = DAYS_LIMIT; // dacă este o constantă
    // $days_limit = get_option('days_limit',100);
    // trebuie să decomentezi una dintre cele de mai sus,
    // în funcție de mecanismul ales
    $where .= " AND post_date < '" . date('y-m-d', strtotime("-{$days_limit} days")) . "'";
    return $where;
}
add_filter('posts_where', 'smbd_cats_by_days');

Bazat pe editarea întrebării și pe această declarație de intenții:

Încerc să afișez doar postările pe care un utilizator nu le-a văzut...

Scrie codul PHP pentru a crea un array cu postările pe care utilizatorul le-a văzut și exclude-le cu post__not_in. Încercarea ta de a băga totul în interogare doar complică lucrurile.

De asemenea, cred că este mai ușor de citit pentru alții dacă este un apel WP_Query sau $wpdb, decât linii și linii de PHP care să ajungă la un parametru de interogare.

Până când vei scrie filtrele și/sau SQL-ul pentru a include totul în interogare, nu va fi mai "ușor de citit" și este discutabil dacă ar fi mai ușor de citit de la bun început. Încerci să faci asta pe calea cea grea. WP_Query nu este capabilă de logică complexă, iar logica complexă în SQL este greu de scris și greu de citit chiar și într-o zi bună.

2 aug. 2013 06:25:02
Comentarii

sau poate un posts_join http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_join

gmazzap gmazzap
2 aug. 2013 06:29:52

Mulțumesc, am înțeles. Voi folosi array_diff() atunci. Mulțumesc. Am votat pozitiv acest răspuns deoarece ai depus efort să răspunzi la întrebarea mea prost formulată.

Drew Baker Drew Baker
2 aug. 2013 20:19:02
4

Excluderea și includerea nu pot fi utilizate împreună, acest cod este folosit în nucleu, deci fie una, fie cealaltă.

...
if ( ! empty($r['include']) ) {
  $incposts = wp_parse_id_list( $r['include'] );
  $r['posts_per_page'] = count($incposts);  // doar numărul de postări incluse
  $r['post__in'] = $incposts;
} elseif ( ! empty($r['exclude']) )
...

Un query $wpdb este ușor dacă singurele argumente de care ai nevoie sunt doar cele pe care le-ai postat.

Această metodă este ușoară, dar dacă nu poți, poți explica de ce?

$exclude = array(1,2,3);
$include = array(3,4,5);
$args = array(
    'post_type'         => 'post',
    'post_status'       => 'publish',
    'posts_per_page'    => 30,
    'post__in'          => array_diff($include, $exclude),
)
$posts = get_posts($args);
2 aug. 2013 05:40:23
Comentarii

Știu că aș putea folosi array_diff() pe variabilele $exclude și $include, dar realitatea este mai complicată decât această întrebare. Trebuie făcut în interogare.

s_ha_dum s_ha_dum
2 aug. 2013 06:11:43

@s_ha_dum Îmi cer scuze, greșeala mea. Dă un vot negativ răspunsului, eu nu pot.

gmazzap gmazzap
2 aug. 2013 06:13:02

Am actualizat interogarea pentru a reflecta toți parametrii pe care îi folosesc. O interogare $wpdb ar putea fi cea mai bună soluție.

Drew Baker Drew Baker
2 aug. 2013 08:29:26

Am fost confuz de ce interogarea mea nu funcționa până când am citit Codex-ul despre WP_Query. Poți folosi doar post__in sau post__not_in. Nu pe ambele împreună în aceeași interogare. Am găsit această soluție și trebuie să spun că este o soluție genială de ocolire a problemei.

Michael Ecklund Michael Ecklund
1 nov. 2017 18:15:43