Utilizzare le condizioni OR in meta_query per l'argomento query_posts
Ho cercato ovunque ma non riesco a trovare una soluzione.
Sto cercando di filtrare alcuni risultati e quando creo un array args come questo e lo passo a query_posts, ho notato che l'SQL generato usa AND invece di OR per il valore 'class_1_days'. Vorrei cambiarlo in OR. Come posso fare? (Sto usando LIKE poiché i dati sono serializzati, altrimenti avrei provato a usare "IN" passando un array. Qual è il modo corretto per procedere?)
$args = array(
'taxonomy' => 'courses',
'term' => 'drawing',
'post_type' => 'school',
'paged' => $paged,
'meta_query' =>
#$checkbox_array,
array(
// Relazione tra le condizioni della meta query
'relation' => 'AND',
array(
'key' => 'instructor',
'value' => '1128',
'compare' => 'LIKE',
),
// Gruppo di condizioni OR per class_1_days
array(
'relation' => 'OR',
array(
'key' => 'class_1_days',
'value' => 'Friday',
'compare' => 'LIKE',
),
array(
'key' => 'class_1_days',
'value' => 'Saturday',
'compare' => 'LIKE',
),
)
)
);
Questo è l'SQL rilevante che viene generato dove ho notato l'AND
[138] => Array
(
[0] => SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id)
INNER JOIN wp_postmeta AS mt2 ON (wp_posts.ID = mt2.post_id) WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (18) ) AND wp_posts.post_type = 'school' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') AND ( (wp_postmeta.meta_key = 'instructor' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%1128%')
AND (mt1.meta_key = 'class_1_days' AND CAST(mt1.meta_value AS CHAR) LIKE '%Friday%')
AND (mt2.meta_key = 'class_1_days' AND CAST(mt2.meta_value AS CHAR) LIKE '%Saturday%') ) GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 5

Usa 'relation' => 'OR'
come nell'esempio del Codex qui sotto:
$args = array(
'post_type' => 'product',
'meta_query' => array(
'relation' => 'OR', /* <-- qui */
array(
'key' => 'color',
'value' => 'blue',
'compare' => 'NOT LIKE'
),
array(
'key' => 'price',
'value' => array( 20, 100 ),
'type' => 'numeric',
'compare' => 'BETWEEN'
)
)
);
$query = new WP_Query( $args );
Questo ti darà una condizione OR
tra tutti i blocchi del meta_query. Se quello che ti serve è qualcosa tipo WHERE "instructor" = 1128 AND (class_1_days = "value1" OR class_1_days = "value2")
allora qualcosa del genere potrebbe funzionare, se i tuoi dati non fossero serializzati.
$args = array(
'taxonomy' => 'courses',
'term' => 'drawing',
'post_type' => 'school',
'paged' => $paged,
'meta_query' =>
array(
array(
'key' => 'instructor',
'value' => '1128',
'compare' => 'LIKE',
),
array(
'key' => 'class_1_days',
'value' => array('Friday','Saturday')
'compare' => 'IN',
)
)
);
Dato che hai dati serializzati, questo sarà difficile. Potresti scrivere un filtro per posts_where
ma mi aspetterei che il risultato sia inefficiente e soggetto a errori.
L'approccio corretto per casi come questo, dove hai bisogno di cercare/filtrare/ordinare per qualche informazione, è, nella mia esperienza, di non memorizzare i dati come array serializzato in primo luogo. Questo è semplicemente l'approccio sbagliato se hai bisogno di query come questa.
Se dovessi prendere in carico questo progetto, ciclerei attraverso i dati che devono essere interrogati in questo modo e risalverei ogni pezzo come una coppia chiave/valore. Le parti che non stai interrogando possono rimanere serializzate. Non c'è un modo (buono) per farlo in MySQL con funzioni MySQL, né come parte della query che stai tentando né come qualche query standalone. Ho visto tentativi di creare una funzione MySQL "unserialize" ma non ne vedo il punto. Risalvare i dati è la strada da percorrere.
Dovrebbe essere una query abbastanza semplice ottenere tutti i dati di class_1_days
. Poi cicla su di essi e salva le parti che devi interrogare come chiavi indipendenti e rimetti il resto come dati serializzati.

Grazie mille per la tua risposta. C'è un modo per fare un AND o OR? Sto cercando di mantenere il bit dell'istruttore. Il tuo esempio li rende tutti OR. Ho solo bisogno che la parte class_1_days sia un OR. Simile a se lo avessi come 'value' => array(bla,bla,bla), 'compare' => IN
In pratica dove Instructor = 'bla' AND value IN (bla,bla,bla)

Grazie @S_ha_dam. C'è un modo per deserializzare il DB? Ho preso questo progetto in seconda battuta quindi non so cosa potrebbe influenzare. Ho visto un link a un'app che faceva proprio questo, ma il link era rotto.

Grazie, tuttavia semplicemente risalvarlo non funzionerà, questo è un ambiente live dove i dati vengono costantemente salvati e class_1_data è solo parte dell'equazione. Ce ne sono multiple come class_0_data, class_2_data, eccetera, e questi vengono aggiunti dagli utenti. Penso che l'approccio migliore possa essere tornare indietro e trovare un modo per reinstallare il modulo e fare in modo che non salvi in formato serializzato (se capisco come) e procedere da lì X-( ... Non avevo menzionato la parte delle altre classi perché pensavo di poterla capire da solo

Dovrai sicuramente rifattorizzare la funzione "save", ma dovrai anche risalvare i dati esistenti, altrimenti ti ritroverai con un mix strano di dati serializzati e non serializzati. Fai funzionare il codice su un server di sviluppo, poi metti quello live in modalità manutenzione per venti minuti in un momento della giornata con poco traffico.

Oh sì, sicuramente dovrò modificare i dati attuali!
Che palle. Pensavo che questa sarebbe stata una correzione facile, uffa!

Aspetta...sentiamo questa...c'è un modo per aggiungere DOPO questo filtro un altro filtro che sarebbe per istruttore?
O addirittura ottenere di nuovo l'array PHP diretto che WordPress sta usando e modificarlo?

Non sono sicuro di aver capito l'ultima domanda, ma tramite i filtri puoi modificare la query per essere praticamente qualsiasi cosa tu voglia. Tuttavia, "aggiungendo" qualcosa, dubito che otterrai una query efficiente.

uh, per esempio sai in PHP avresti il tuo array effettivo come classes[1][bla], classes[2][bla] ecc., se sapessi come si chiama quell'array potrei potenzialmente fare qualche ricerca nell'array PHP e usare regex per filtrarlo da solo dopo aver ottenuto i risultati desiderati dall'istruzione OR che hai fornito prima.

Secondo il codex di WordPress, gli array annidati possono essere utilizzati per costruire query complesse. Nel tuo esempio avrai bisogno di qualcosa come questo:
$args = array(
'taxonomy' => 'courses',
'term' => 'drawing',
'post_type' => 'school',
'paged' => $paged,
'meta_query' =>
array(
'relation' => 'AND', // relazione predefinita
array(
'key' => 'instructor',
'value' => '1128',
'compare' => 'LIKE',
),
array(
'relation' => 'OR',
array(
'key' => 'class_1_days',
'value' => 'Friday',
'compare' => 'LIKE',
),
array(
'key' => 'class_1_days',
'value' => 'Saturday',
'compare' => 'LIKE',
),
)
)
);

Ho dovuto scavare per trovare questo. Ho una query complessa che riguarda questo argomento. Sei stato votato così tante volte che penso farò una nuova domanda basandomi su questo. Sono molto interessato a vedere come la community sta affrontando questo tipo di problema al momento, sinceramente.
