WordPress snippet: estrarre meta value con get_posts()

Lavorando con un Custom Post Type (CPT) viene spontaneo utilizzare le funzioni interne di WordPress per visualizzare e filtrare i post di questo tipo. Sia che si usi la get_posts() sia che si crei direttamente un oggetto WP_Query, risulta comodissimo poter creare loop personali sulle proprie tipologie di post. Inoltre WordPress permette di effettuare filtri per tassionomie personali, sul count, sull’ordine, arrivando fino ai meta data. Utilissimo, infatti, è il processo che permette di indicare nelle condizioni di where che tipo di meta data confrontare e con che regole. Questa caratteristiche non è utile solo per i CPT ma anche per i normali post. Capita spesso di estendere le informazioni di un post (o di una pagina) con campi personali che vanno a finire nella tabella post meta. Questi valori aggiuntivi, oltre ad essere utilizzati durante la visualizzazione, possono essere utilizzati per filtrare e ordinare i nostri post.

Ad esempio ecco come estrarre una serie di CPT a cui gli è stata aggiunta una data personale (non quella del post) nei post meta:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* Creo le condizioni di where */
$meta_query = array(                            
    array(                                      
        'key'     => 'my_meta_key',  
        'value'   => array(                      
            $today,                              
            $maxDate                            
        ),                                      
        'type'    => 'numeric',                  
        'compare' => 'BETWEEN'                  
    )                                            
);

/* Argomenti standard, vedi WP_Query */
$args = array(                                  
    'numberposts' => 10,              
    'post_status' => 'publish',                  
    'post_type'   => 'my_custom_type',
    'meta_key'    => 'my_meta_key',  
    'orderby'     => 'meta_value',              
    'order'       => 'ASC',                      
    'meta_query'  => $meta_query                
);                                              
$posts = get_posts($args);

Nell’esempio di sopra vengono estratti 10 post del tipo my_custom_type che hanno la my_meta_key compresa (between) tra $today e $maxDate. La data è memorizzata sempre come stringa, in quanto come sapete nel meta dati non è possibile scegliere il tipo di dato da memorizzare, e il tipo stringa (insieme alla serializzazione) li copra in pratica tutti; dagli interi, agli array fino ad arrivare agli oggetti. La data, inserita nel formato YYYYMMDD può essere così usata sia come filtro durante una ricerca, sia per ordinare i nostri post.
Quello che il codice sopra non fa, tuttavia, e restituirci il valore della my_meta_key. Lo usa per trovare gli elementi ma nell’array $posts non ne abbiamo traccia. Quello che sorgerebbe spontaneo fare e utilizzare successivamente, casomai in un altro loop foreach la funzione get_post_meta(), appesantendo non poco l’intero codice: una select, più n get_post_meta() per ogni post estratto.

Fortunatamente WordPress mette a disposizione uno dei suoi filtri magici in grado di alterare la select SQL che viene prodotta al suo interno quando usiamo la get_posts(), stesso discorso se avete creato voi un oggetto WP_Query.
Tramite il filtro posts_fields è possibile aggiungere colonne da estrarre durante una normale get_posts() che di solito si preoccupa solo di estrarre le colonne della tabella posts.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/* Creo le condizioni di where */
$meta_query = array(                                  
    array(                                            
        'key'     => 'my_meta_key',      
        'value'   => array(                          
            $today,                                  
            $maxDate                                  
        ),                                            
        'type'    => 'numeric',                      
        'compare' => 'BETWEEN'                        
    )                                                
);            

/* Argomenti standard, vedi WP_Query */                                        
$args       = array(                                  
    'numberposts'      => 10,              
    'suppress_filters' => false,                      
    'post_status'      => 'publish',                  
    'post_type'        => 'my_custom_type',
    'meta_key'         => 'my_meta_key',  
    'orderby'          => 'meta_value',              
    'order'            => 'ASC',                      
    'meta_query'       => $meta_query                
);

/* Aggiungo il filtro per aggiungere colonne */
add_filter( 'posts_fields', function( $fields ) {
  global $wpdb;
  $fields .= sprintf( ', %s.meta_key, %s.meta_value ', $wpdb->postmeta, $wpdb->postmeta );
  return ( $fields );                                                                    
}, 10, 1 );

$posts = get_posts( $args );

In $posts adesso avremmo un array di oggetti con una proprietà in più (anzi due): le colonne meta_key e meta_value. Così, possiamo visualizzare ed eventualmente rielaborare ulteriormente, il nostro dato.

Non potevo usare una custom select SQL?

In teoria si, ma in pratica non ne vale la pena. Le funzioni interne di WordPress è vero che alla fine altro non fanno che generare uno statement SQL, ma fanno e permettono un bel po’ di cosine in più.

  • Sanitizzano i parametri
  • Ci nascondono la complessità delle JOIN in gioco
  • Sono sempre aggiornate e non ci costringono a conoscere nel dettaglio più spinto l’intero database di sistema WordPress
  • Se qualche altro plugin ha alterato il loro funzionamento tramite i filtri, vedi WPML, tutto funzionerà alla perfezione

Per chi volesse approfondire tutti i filtri possibili, veda qui.

  • vik

    Giustappunto sto lavorando ad un progetto e il cliente mi ha chiesto di mostrare tutte le news (che sono CPT) in un calendario… Perfetto!

  • http://www.s-2000.eu luigi

    Ciao mi chiamo Luigi ho usato Custom Content Type manager per la realizzazione di una grossa fiera ho realizzato un Custom type chiamato “Espositori” dove ho creato i dettagli dell’espositore come:
    Tipologia
    Categoria
    N° Stand
    Inserimento foto
    etc…

    Ho necessita di far visualizzare in modo corretto in una pagina personalizzata tutti gli espositori di un certa tipologia esempio:

    Motorizzazioni
    n° stand Nome Espositore (con link che porti alla mia scheda precedentemente creata con Custom Content Type manager)
    n° stand Nome Espositore (con link che porti alla mia scheda precedentemente creata con Custom Content Type manager)
    n° stand Nome Espositore (con link che porti alla mia scheda precedentemente creata con Custom Content Type manager)

    Fiori
    n° stand Nome Espositore (con link che porti alla mia scheda precedentemente creata con Custom Content Type manager)
    n° stand Nome Espositore (con link che porti alla mia scheda precedentemente creata con Custom Content Type manager)
    n° stand Nome Espositore (con link che porti alla mia scheda precedentemente creata con Custom Content Type manager)

    etc…..

    in più se è possibile chreare a inzio pagina un search per Tipologia – Nome – Categoria

    come posso settare queste cose con WP_Query ?

    AIUTAMI!!!! Ti Ringrazio anticipatamente ciao Luigi