Utilizzo di $wpdb per interrogare post con meta_value contenente il post_id corrente

4 ago 2013, 09:20:14
Visualizzazioni: 15.7K
Voti: 3

Sto cercando di utilizzare $wpdb per recuperare un elenco di post dal database dove il meta_value nella tabella wp_postmeta contiene l'ID del post corrente tra virgolette. Es. "10"

Le virgolette servono per assicurarsi che 10 non corrisponda anche a 100, ecc.

Riesco a farlo funzionare quando incollo il valore esatto del meta_value, cioè: a:1:{i:0;s:2:"10";}, ma restituisce anche tutte le revisioni, non solo il post più recente.

Ecco il codice che sto attualmente utilizzando:

   $id = get_the_ID();
   $rows = $wpdb->get_results($wpdb->prepare( 
                  "
                  SELECT * 
                  FROM wp_postmeta
                  WHERE meta_key LIKE %s
                      AND meta_value = %s
                  ",
                  'roles_%_production',
                  '%"' . $id . '"%'
              ));

        // ciclo attraverso i risultati
        if( $rows ) {
        ......
        }

Ogni suggerimento sarebbe molto apprezzato.

Grazie

0
Tutte le risposte alla domanda 3
1

Nel codice che hai pubblicato non recuperi una 'lista di post' come dici, ma recuperi una lista di righe nella tabella meta. Se vuoi recuperare realmente una lista di post utilizza WP_Query con il parametro meta_query.

Qualcosa come:

$id = '10'; // valore unserializzato

$args = array(
  'post_type' => 'post',
  'post_status' => 'publish',
  'posts_per_page' => -1,
  'meta_query' => array(
    array(
      'key' => 'roles_%_production',
      'value' => $id,
      'compare' => 'LIKE'
    )
  )
);
$query = new WP_Query( $args );
$rows = $query->get_posts();

Se vuoi usare $wpdb (non so perché) la query corretta è qualcosa tipo:

<?php
$id = '10'; // valore unserializzato

global $wpdb;
$rows = $wpdb->get_col( $wpdb->prepare(
  "SELECT DISTINCT $wpdb->posts.ID FROM $wpdb->posts, $wpdb->postmeta
  WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id AND
  $wpdb->posts.post_status = 'publish' AND
  $wpdb->posts.post_type = 'post' AND
  $wpdb->postmeta.meta_key = %s AND
  meta_value = %s",
  'roles_%_production',
  $id
) );
?>

$rows conterrà un array di ID dei post. Ho fatto questa modifica per dare senso all'uso di $wpdb. Se vuoi recuperare tutti i campi usa SELECT * invece di SELECT DISTINCT $wpdb->posts.ID, usa $wpdb->get_results invece di $wpdb->get_col e aggiungi la riga GROUP BY $wpdb->posts.ID alla query.

4 ago 2013 11:29:04
Commenti

Concordo. Usare WP_Post è la strada giusta.

Cedon Cedon
31 lug 2017 04:16:36
0

Due note:

Ricerca nei metadati

La regola è semplice: i metadati serializzati (come un array convertito in a:1:{i:0;s:2:"10";}) non sono pensati per essere ricercabili. Dovrai convertire il tuo dataset in valori singoli, così potrai effettuare ricerche corrette con meta_query.

L'unico modo veramente funzionante per effettuare questa ricerca è interrogare tutti i dati, poi deserializzarli, renderizzarli se corrispondono ai tuoi criteri o saltarli. Ci sono abbastanza discussioni e domande/risposte su SO che coprono questo argomento.

Prepared statements

C'è like_escape(), che deve essere usato così:

"%".like_escape( $string )."%"

Il motivo per cui devi aggiungere i caratteri % all'inizio e alla fine è semplice: puoi decidere tu stesso se il LIKE deve avvenire su entrambi i lati o solo su uno (inizio, fine, entrambi).

4 ago 2013 14:51:57
0

Le virgolette servono per assicurarsi che 10 non corrisponda anche a 100 ecc.

Funziona quando incollo il valore esatto del meta, cioè: a:1:{i:0;s:2:"10";}

Questo perché nella tua query WHERE, hai usato = dove il valore contiene %. Usando LIKE invece risolveresti questo problema specifico. Cambia meta_value = %s in meta_value LIKE %s, e la tua query dovrebbe funzionare come se avessi usato la stringa serializzata completa.

restituisce anche tutte le revisioni, non solo il post più recente.

Assicurati di specificare il tipo di post e lo stato corretti quando esegui la query. Se vuoi includere tutti i post che non sono revisioni, dovrai unire la tabella dei post (prima della tua clausola WHERE).

LEFT JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->postmeta.post_id

e includi la seguente riga nella tua clausola WHERE (collegata da un AND).

$wpdb->posts.post_type NOT IN ('revision')
31 lug 2017 04:10:03