Cum să returnezi doar anumite câmpuri folosind get_posts()
Î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.

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.

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!

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

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

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/

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

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
