Cum să returnezi doar anumite câmpuri folosind get_posts()

30 iul. 2013, 06:21:35
Vizualizări: 40.4K
Voturi: 13

Încerc să obțin doar câmpurile de care am nevoie folosind funcția get_posts() în WordPress. În prezent, am următorul cod:

    $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);

Acest cod funcționează bine dacă vreau să obțin doar ID-ul. Dar dacă vreau să obțin permalink-ul sau titlul articolului împreună cu ID-urile, aici nu sunt sigur ce să fac. Am încercat deja următoarele:

'fields' => array('ids', 'post_titles')
'fields' => 'ids,post_titles'
'fields' => 'ids,titles'
'fields' => array('ids','titles')

Dar nimic nu funcționează, presupun că singurul câmp pe care îl recunoaște este câmpul ids. Există vreo altă modalitate de a face acest lucru dacă nu este posibil să îl realizăm folosind get_posts()? Mulțumesc anticipat.

0
Toate răspunsurile la întrebare 6
1

get_posts deleghează sarcina grea către WP_Query și dacă analizezi sursa acelei clase, poți vedea că există doar un număr limitat de opțiuni cu acel argument fields. Există doar trei opțiuni în acel switch -- ids, id=>parent, și cazul implicit, totul.

Poți utiliza filtrul posts_fields pentru a modifica ce câmpuri sunt returnate, deși se pare că trebuie să transmiți 'suppress_filters => false în argumente pentru ca acest filtru să funcționeze. Ar trebui să arate cam așa:

function alter_fields_wpse_108288($fields) {
  return 'ID,post_title'; // etc
}
add_filter('posts_fields','alter_fields_wpse_10888');

Cu toate acestea, există o problemă mai mare. Obiectele post care sunt returnate sunt create prin apelarea get_post și acesta nu respectă valorile transmise în interogarea originală și nu văd nicio modalitate de a schimba ce este returnat nici în get_posts, nici în clasa WP_Post în sine.

30 iul. 2013 06:50:38
Comentarii

Se pare că parametrul 'fields' a fost introdus într-o versiune 5.x a WP. Simplu folosind get_posts(array('fields' => 'ids')) ar obține postări doar cu ID-uri fără a folosi filtrul posts_fields. Te rog să mă corectezi dacă greșesc, pentru că a funcționat pentru mine în cea mai recentă versiune wp (5.2.4) fără a adăuga filtrul. Mulțumesc!

AhmadKarim AhmadKarim
25 oct. 2019 18:12:25
0

Uită-te la aceasta

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);
}

Aceasta este o funcție care imită get_posts dar cu capacitatea de a obține câmpurile dorite. Atenție: această funcție nu este get_posts și are 2 mari limitări: rulează doar în tabela posts, astfel încât interogările de taxonomie și meta nu pot fi efectuate!

Totuși, interogarea se poate baza pe toate câmpurile postărilor și pe unele argumente 'speciale' precum include, exclude și search.

Partea bună este aceasta: câmpurile pe care le puteți obține sunt toate câmpurile din tabela posts. Doar transmiteți o listă sau un array în argumentul fields. Bonus: dacă se transmite un singur câmp, se returnează un array unidimensional de șiruri sau întregi (în loc de un array de obiecte).

Lista argumentelor disponibile:

$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 nume de câmp valid
  'order', // string 'ASC', sau 'DESC',
  'posts_per_page', // int
  'include', // array (sau șir separat prin virgulă) de ID-uri de postări
  'exclude', // array (sau șir separat prin virgulă) de ID-uri de postări
  'search', // string dacă este transmis, va căuta în titlul postării
  'fields', // array (sau șir separat prin virgulă) de câmpuri de obținut.
            // Dacă este transmis un singur câmp, se returnează un array 'plat' 
);

Exemple de utilizare

// Obține data și titlul paginilor care conțin 'Hello' în titlu
$pages_hello = get_posts_fields("post_type=page&search=Hello&fields=post_date,post_title");


// alt exemplu
$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);


// Încă unul, doar pentru distracție ;)
$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 "Am $count fișiere de tipul $mime" . PHP_EOL;
}
31 iul. 2013 07:17:56
1

Poți folosi doar 'ids' sau 'id=>parent' pentru parametrul fields.

Dacă specifici altceva, vor fi returnate toate câmpurile (acesta este comportamentul implicit).

Totuși, ar fi bine dacă WordPress ar putea adăuga următoarele 2 opțiuni: 'titles' și 'ids_and_titles'.

Nu sunt conștient de vreo metodă de a trimite un array pentru acest parametru. De asemenea, cred că nu se va întâmpla niciodată, având în vedere limitele răspunsului dat de G. M.

Mai multe informații: http://codex.wordpress.org/Class_Reference/WP_Query#Return_Fields_Parameter

25 ian. 2014 19:43:28
Comentarii

id=>parent nu este un argument valid.

kaiser kaiser
25 ian. 2014 20:47:14
0

Interesant, poți face asta folosind WP Rest API și parametrul _fields

https://yoursite.com/wp-json/wp/v2/posts?_fields=author,id,excerpt,title,link

Mai multe informații despre API aici: https://developer.wordpress.org/rest-api/

5 iul. 2021 11:20:11
0

Mulțumesc gmazzap pentru acea funcție! Căutam o soluție pentru a obține câteva câmpuri personalizate într-un singur apel cu get_posts, așa că am extins-o pentru câmpurile personalizate din tabelul 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);
}

Puteți folosi și orderby pentru acele câmpuri. Un mic exemplu:

$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

Dacă dorești să afișezi titlul articolului în interiorul unui șablon sau într-un plugin, poți utiliza:

get_the_title($ID)

Vezi referința WordPress: http://codex.wordpress.org/Function_Reference/get_the_title

Dacă folosești funcția în afara buclei, parametrul $ID este obligatoriu. În orice caz, probabil va fi folosită astfel:

Poți de asemenea utiliza:

the_permalink() - pentru a obține link-ul permanent al articolului the_title() - pentru a obține titlul articolului

Acestea sunt toate funcții-template din WordPress. O listă completă a funcțiilor-template pe care le poți utiliza poate fi găsită aici: http://codex.wordpress.org/Template_Tags

30 iul. 2013 07:53:05
Comentarii

Cum răspunde acest lucru la întrebare?

anastymous anastymous
10 oct. 2019 04:41:41