Come restituire solo determinati campi usando get_posts()
Sto cercando di ottenere solo i campi di cui ho bisogno usando la funzione get_posts()
in WordPress. Attualmente ho il seguente codice:
$posts_args = array(
'orderby' => 'post_date',
'order' => 'DESC',
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 5,
'fields' => 'ids'
);
$post_ids_r = get_posts($posts_args);
Questo funziona bene se voglio ottenere solo l'id. Ma se voglio ottenere il permalink o il titolo del post insieme agli id non sono sicuro su come procedere. Ho già provato quanto segue:
'fields' => array('ids', 'post_titles')
'fields' => 'ids,post_titles'
'fields' => 'ids,titles'
'fields' => array('ids','titles')
Ma nulla funziona, immagino che l'unico campo che riconosce sia ids
. C'è un altro modo per farlo se non è realmente possibile utilizzare get_posts()
? Grazie in anticipo.

get_posts
delega il lavoro pesante a WP_Query
e se osservi il codice sorgente di quella classe puoi vedere che ci sono solo un numero limitato di opzioni con l'argomento fields
. Ci sono solo tre opzioni in quello switch
-- ids
, id=>parent
, e il caso predefinito, tutto.
Puoi usare il filtro posts_fields
per modificare quali campi vengono restituiti, anche se sembra che tu debba passare 'suppress_filters => false
negli argomenti per far funzionare quel filtro. Dovrebbe essere qualcosa del genere:
function alter_fields_wpse_108288($fields) {
return 'ID,post_title'; // ecc
}
add_filter('posts_fields','alter_fields_wpse_10888');
Tuttavia, c'è un problema più grande. Gli oggetti post che vengono restituiti sono creati da una chiamata a get_post
e non rispetta i valori passati alla query originale e non vedo un modo per cambiare ciò che viene restituito né in get_posts
né nella classe WP_Post
stessa.

Sembra che il parametro 'fields'
sia stato introdotto in una versione 5.x di WP. Semplicemente usando get_posts(array('fields' => 'ids'))
si ottengono i post con solo gli ID senza dover utilizzare il filtro posts_fields
. Correggimi se sbaglio, perché ha funzionato per me nell'ultima versione di wp (5.2.4) senza aggiungere il filtro. Grazie!

Dai un'occhiata a questo
function get_posts_fields( $args = array() ) {
$valid_fields = array(
'ID'=>'%d', 'post_author'=>'%d',
'post_type'=>'%s', 'post_mime_type'=>'%s',
'post_title'=>false, 'post_name'=>'%s',
'post_date'=>'%s', 'post_modified'=>'%s',
'menu_order'=>'%d', 'post_parent'=>'%d',
'post_excerpt'=>false, 'post_content'=>false,
'post_status'=>'%s', 'comment_status'=>false, 'ping_status'=>false,
'to_ping'=>false, 'pinged'=>false, 'comment_count'=>'%d'
);
$defaults = array(
'post_type' => 'post',
'post_status' => 'publish',
'orderby' => 'post_date',
'order' => 'DESC',
'posts_per_page' => get_option('posts_per_page'),
);
global $wpdb;
$args = wp_parse_args($args, $defaults);
$where = "";
foreach ( $valid_fields as $field => $can_query ) {
if ( isset($args[$field]) && $can_query ) {
if ( $where != "" ) $where .= " AND ";
$where .= $wpdb->prepare( $field . " = " . $can_query, $args[$field] );
}
}
if ( isset($args['search']) && is_string($args['search']) ) {
if ( $where != "" ) $where .= " AND ";
$where .= $wpdb->prepare("post_title LIKE %s", "%" . $args['search'] . "%");
}
if ( isset($args['include']) ) {
if ( is_string($args['include']) ) $args['include'] = explode(',', $args['include']);
if ( is_array($args['include']) ) {
$args['include'] = array_map('intval', $args['include']);
if ( $where != "" ) $where .= " OR ";
$where .= "ID IN (" . implode(',', $args['include'] ). ")";
}
}
if ( isset($args['exclude']) ) {
if ( is_string($args['exclude']) ) $args['exclude'] = explode(',', $args['exclude']);
if ( is_array($args['exclude']) ) {
$args['exclude'] = array_map('intval', $args['exclude']);
if ( $where != "" ) $where .= " AND ";
$where .= "ID NOT IN (" . implode(',', $args['exclude'] ). ")";
}
}
extract($args);
$iscol = false;
if ( isset($fields) ) {
if ( is_string($fields) ) $fields = explode(',', $fields);
if ( is_array($fields) ) {
$fields = array_intersect($fields, array_keys($valid_fields));
if( count($fields) == 1 ) $iscol = true;
$fields = implode(',', $fields);
}
}
if ( empty($fields) ) $fields = '*';
if ( ! in_array($orderby, $valid_fields) ) $orderby = 'post_date';
if ( ! in_array( strtoupper($order), array('ASC','DESC')) ) $order = 'DESC';
if ( ! intval($posts_per_page) && $posts_per_page != -1)
$posts_per_page = $defaults['posts_per_page'];
if ( $where == "" ) $where = "1";
$q = "SELECT $fields FROM $wpdb->posts WHERE " . $where;
$q .= " ORDER BY $orderby $order";
if ( $posts_per_page != -1) $q .= " LIMIT $posts_per_page";
return $iscol ? $wpdb->get_col($q) : $wpdb->get_results($q);
}
È una funzione che emula get_posts ma con la capacità di ottenere i campi desiderati. Attenzione: questa funzione non è get_posts e ha 2 grandi limitazioni: opera solo sulla tabella posts quindi non è possibile eseguire query su tassonomia e meta!
Tuttavia, la query può basarsi su tutti i campi del post e su alcuni argomenti 'speciali' come include
, exclude
e search
.
La parte positiva è questa: i campi che puoi recuperare sono tutti i campi della tabella posts. Basta passare una lista o un array nell'argomento fields
.
Bonus: passando un solo campo viene restituito un array monodimensionale di stringhe o interi (invece di un array di oggetti).
Lista degli argomenti disponibili:
$available_args = array(
'ID', // int
'post_author', // string
'post_type', // string
'post_mime_type', // string
'post_name', // string
'post_date', // string
'post_modified', // string
'menu_order', // int
'post_parent', // int
'post_status', // string
'comment_status', // string
'comment_count', // int
'orderby', // string, un nome di campo valido
'order', // string 'ASC', o 'DESC',
'posts_per_page', // int
'include', // array (o stringa separata da virgole) di ID post
'exclude', // array (o stringa separata da virgole) di ID post
'search', // stringa, se passata cerca nel titolo del post
'fields', // array (o stringa separata da virgole) di campi da recuperare.
// Se viene passato solo 1 campo viene restituito un array 'piatto'
);
Esempi di utilizzo
// Recupera la data e il titolo delle pagine che contengono 'Hello' nel titolo
$pages_hello = get_posts_fields("post_type=page&search=Hello&fields=post_date,post_title");
// un altro esempio
$args = array(
'post_type' => 'custom_post',
'posts_per_page' => -1,
'post_parent' => 1,
'include' => array(2,3,4),
'exclude' => '6,8,10',
'fields' => array('post_title', 'comment_status')
);
get_posts_fields($args);
// Un altro ancora, solo per divertimento ;)
$args = array(
'post_type' => 'attachment', 'posts_per_page' => -1,
'post_status' => 'inherit', 'fields' => 'post_mime_type'
);
foreach ( array_count_values ( get_posts_fields($args) ) as $mime => $count ) {
echo "Ho $count media di tipo $mime" . PHP_EOL;
}

Puoi utilizzare solo 'ids'
o 'id=>parent'
per il parametro fields
.
Se inserisci qualcos'altro, verranno restituiti tutti i campi (questo è il comportamento predefinito).
Sarebbe comunque utile se WordPress aggiungesse le seguenti 2 opzioni: 'titles'
e 'ids_and_titles'
.
Non sono a conoscenza di un modo per passare un array per questo parametro. Penso inoltre che non accadrà mai, visti i limiti della risposta fornita da G. M.
Maggiori informazioni: http://codex.wordpress.org/Class_Reference/WP_Query#Return_Fields_Parameter

Interessante notare che puoi farlo con la WP Rest API utilizzando il parametro _fields
https://yoursite.com/wp-json/wp/v2/posts?_fields=author,id,excerpt,title,link
Maggiori informazioni sull'API qui: https://developer.wordpress.org/rest-api/

Grazie gmazzap per questa funzione! Stavo cercando una soluzione per ottenere alcuni campi personalizzati insieme con get_posts, quindi mi sono permesso di estenderla per includere i campi personalizzati della tabella postmeta:
function get_posts_fields($args = array())
{
$valid_fields = array(
'ID' => '%d',
'post_author' => '%d',
'post_type' => '%s',
'post_mime_type' => '%s',
'post_title' => false,
'post_name' => '%s',
'post_date' => '%s',
'post_modified' => '%s',
'menu_order' => '%d',
'post_parent' => '%d',
'post_excerpt' => false,
'post_content' => false,
'post_status' => '%s',
'comment_status' => false,
'ping_status' => false,
'to_ping' => false,
'pinged' => false,
'comment_count' => '%d',
'custom_fields' => false,
);
$defaults = array(
'post_type' => 'post',
'post_status' => 'publish',
'orderby' => 'post_date',
'order' => 'DESC',
'posts_per_page' => get_option('posts_per_page')
);
global $wpdb;
$args = wp_parse_args($args, $defaults);
$where = "";
$meta = "";
$groupBy = "";
foreach ($valid_fields as $field => $can_query) {
if (isset($args[$field]) && $can_query) {
if ($where != "") {
$where .= " AND ";
}
$where .= $wpdb->prepare(
$wpdb->posts.".".$field . " = " . $can_query,
$args[$field]
);
}
}
if (isset($args['search']) && is_string($args['search'])) {
if ($where != "") {
$where .= " AND ";
}
$where .= $wpdb->prepare(
"post_title LIKE %s",
"%" . $args['search'] . "%"
);
}
if (isset($args['include'])) {
if (is_string($args['include'])) {
$args['include'] = explode(',', $args['include']);
}
if (is_array($args['include'])) {
$args['include'] = array_map('intval', $args['include']);
if ($where != "") {
$where .= " OR ";
}
$where .= $wpdb->posts.".ID IN (" . implode(',', $args['include']) . ")";
}
}
if (isset($args['exclude'])) {
if (is_string($args['exclude'])) {
$args['exclude'] = explode(',', $args['exclude']);
}
if (is_array($args['exclude'])) {
$args['exclude'] = array_map('intval', $args['exclude']);
if ($where != "") {
$where .= " AND ";
}
$where .= $wpdb->posts.".ID NOT IN (" . implode(',', $args['exclude']) . ")";
}
}
extract($args);
$iscol = false;
if (isset($fields)) {
if (is_string($fields)) {
$fields = explode(',', $fields);
}
if (is_array($fields)) {
$fields = array_intersect($fields, array_keys($valid_fields));
if (count($fields) == 1) {
$iscol = true;
}
for($i = 0; $i < count($fields); $i++) {
$fields[$i] = "$wpdb->posts.$fields[$i]";
}
}
}
if (isset($args['custom_fields'])) {
if (is_string($args['custom_fields'])) {
$args['custom_fields'] = explode(',', $args['custom_fields']);
}
if (is_array($args['custom_fields'])) {
foreach( $args['custom_fields'] as $custom_field) {
$fields[] = "MAX(CASE WHEN df_postmeta.meta_key = '$custom_field' then df_postmeta.meta_value ELSE NULL END) as $custom_field";
}
$meta = " LEFT JOIN $wpdb->postmeta ON ( $wpdb->postmeta.post_id = $wpdb->posts.ID)";
$groupBy = " GROUP BY $wpdb->posts.ID, $wpdb->posts.post_title";
}
}
if (empty($fields)) {
$fields = '*';
} else {
$fields = implode(',', $fields);
}
if( in_array($orderby, $valid_fields) ) {
$orderby = $wpdb->posts.'.'.$orderby;
}else if( isset( $args['custom_fields']) && in_array($orderby, $args['custom_fields']) ) {
$orderby = $orderby;
} else {
$orderby = $wpdb->posts.'.post_date';
}
if (!in_array(strtoupper($order), array('ASC', 'DESC'))) {
$order = 'DESC';
}
if (!intval($posts_per_page) && $posts_per_page != -1) {
$posts_per_page = $defaults['posts_per_page'];
}
if ($where == "") {
$where = "1";
}
$q = "SELECT $fields FROM $wpdb->posts " . $meta . " WHERE " . $where;
$q .= $groupBy;
$q .= " ORDER BY $orderby $order";
if ($posts_per_page != -1) {
$q .= " LIMIT $posts_per_page";
}
print $q;
return $iscol ? $wpdb->get_col($q) : $wpdb->get_results($q);
}
Puoi anche utilizzare l'ordinamento (orderby) per questi campi. Un piccolo esempio:
$args = array(
'post_type' => 'projects',
'posts_per_page' => -1,
'fields' => array('ID', 'post_title'),
'orderby' => 'project_clients',
'order' => 'DESC',
'custom_fields' => array(
'project_clients',
'project_dop'
),
);
$projects = get_posts_fields($args);

Se vuoi visualizzare il titolo del post all'interno di un template o in un plugin, puoi utilizzare:
get_the_title($ID)
Consulta la reference di WordPress: http://codex.wordpress.org/Function_Reference/get_the_title
Se lo stai utilizzando al di fuori del loop, l'$ID è obbligatorio. In ogni caso, verrà probabilmente utilizzato in questo modo:
Puoi anche utilizzare:
the_permalink() - per recuperare il permalink del post the_title() - per recuperare il titolo del post
Questi sono tutti tag template di WordPress. Una lista completa dei tag template che puoi utilizzare si trova qui: http://codex.wordpress.org/Template_Tags
