Come restituire solo determinati campi usando get_posts()

30 lug 2013, 06:21:35
Visualizzazioni: 40.4K
Voti: 13

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.

0
Tutte le risposte alla domanda 6
1

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.

30 lug 2013 06:50:38
Commenti

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!

AhmadKarim AhmadKarim
25 ott 2019 18:12:25
0

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;
}
31 lug 2013 07:17:56
1

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

25 gen 2014 19:43:28
Commenti

id=>parent non è un argomento valido.

kaiser kaiser
25 gen 2014 20:47:14
0

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/

5 lug 2021 11:20:11
0

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);
18 mar 2020 22:15:25
1
-1

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

30 lug 2013 07:53:05
Commenti

Come risponde questa risposta alla domanda?

anastymous anastymous
10 ott 2019 04:41:41