Adăugarea de date suplimentare la obiectul WP_Post
Doresc să adaug elemente suplimentare la datele returnate ca WP_Post
. Astfel, pentru fiecare funcție/interogare care returnează un obiect WP_Post, vreau ca datele mele suplimentare să fie incluse.
Exemplu de rezultat returnat:
WP_Post (object) => [
// Date standard returnate de WP_Post
ID => int,
post_author => string,
post_name => string,
post_type => string,
post_title => string,
post_date => string,
post_date_gmt => string,
post_content => string,
post_excerpt => string,
post_status => string,
comment_status => string,
ping_status => string,
post_password => string,
post_parent => int,
post_modified => string,
post_modified_gmt => string,
comment_count => string,
menu_order => string,
// Date suplimentare pe care vreau să le adaug
extra_data_1 => array,
more_data_key => string,
another_added => string
]
De exemplu, când funcțiile get_post()
sau get_page_by_path()
sunt executate, acestea vor returna obiectul WP_Post împreună cu datele mele suplimentare.
Am încercat să găsesc hook-ul/filtrul potrivit, dar fără succes.
Sper că pot face ceva de genul:
// Acesta este cod conceptual
add_action('pre_wp_post_return', function($data) {
$data->extra_data_1 = get_post_meta($data->ID, 'extra_data');
$data->more_data_key = get_post_meta($data->ID, 'more_data', true);
$data->another_added = get_post_meta($data->ID, 'another_data', true);
return $data;
});
Motivația mea este că trebuie să construiesc un API personalizat pentru WP care folosește diverse funcții native care returnează obiecte WP_Post. Posibilitatea de a adăuga datele mele suplimentare într-un singur loc m-ar scuti de duplicarea codului.
Sper că am fost suficient de clar. Orice ajutor ar fi minunat!
Dacă datele tale suplimentare fac referire directă la o meta-informație a postării, nu trebuie să faci nimic, deoarece WP_Post
implementează metodele »magice« __isset()
și __get()
care interoghează direct cheile meta ale postării (cu excepția următoarelor patru chei: page_template
, post_category
, tags_input
și ancestors
). Iată un exemplu rapid care arată comportamentul:
<?php
$post_id = 42;
$meta_key = 'extra_data_1';
add_post_meta( $post_id, $meta_key, [ 'some', 'value' ], TRUE );
$post = get_post( $post_id );
var_dump( $post->{$meta_key} ); // (array) ['some', 'value']
În orice alt caz, folosește filtrul posts_results
:
<?php
add_filter(
'posts_results',
function( array $posts, WP_Query $query ) {
foreach ( $posts as $post ) {
$post->extra_data_1 = get_post_meta( $post->ID, 'extra_data' );
// și așa mai departe …
}
return $posts;
},
10,
2
);
Totuși, aș sugera să folosești o abordare orientată pe obiecte și să creezi propriile interfețe de entități, care să urmeze domeniul tău de problemă. Implementările vor înfășura apoi instanțele WP_Post
ca o dependență. De exemplu, să presupunem că lucrezi cu cărți:
<?php
namespace Wpse240042\Type;
use WP_Post;
interface Book {
/**
* @return string
*/
public function title();
/**
* @return string
*/
public function publisher();
/**
* @return int
*/
public function year();
}
class WpPostBook implements Book {
/**
* @var WP_Post
*/
private $post;
/**
* @param WP_Post $post
*/
public function __construct( WP_Post $post ) {
$this->post = $post;
}
/**
* @return string
*/
public function title() {
return $this->post->post_title;
}
/**
* @return string
*/
public function publisher() {
return get_post_meta( $this->post->ID, '_book_publisher', TRUE );
}
/**
* @return int
*/
public function year() {
return get_post_meta( $this->post->ID, '_book_publisher', TRUE );
}
}
Logica ta de afaceri poate apoi să se bazeze pe structura unei cărți prin indicarea tipului Book
la fiecare dependență. Pentru a obține o listă de cărți, poți implementa o fabrică într-un prim pas care să înfășureze un WP_Query
sau să preia argumente WP_Query și să returneze o listă de instanțe de cărți. Nu ar trebui să folosești filtrul posts_results
în acest caz pentru a înlocui WP_Query::posts
cu o listă de instanțe Type\Book
pentru a nu strica consistența tipului în întregul nucleu WP.

TLDR; Nu poți și nici nu ar trebui.
Este imposibil să extinzi clasa WP_post
cu câmpuri suplimentare, deoarece a fost definită ca 'final'. Poate ai putea ocoli acest lucru prin încapsularea clasei într-o altă clasă (tutorial), dar tot nu este recomandat.
Toate tipurile de teme și plugin-uri se bazează pe faptul că metadatele sunt stocate ca metadate. Poate reuși să funcționeze acum, dar vei regreta probabil în viitor, când vei descoperi că un plugin pe care dorești să-l folosești nu poate gestiona modul în care ai stocat metadatele.

El vrea doar să adauge proprietăți publice la un obiect arbitrar. Acest lucru este posibil indiferent de extensibilitatea declarației clasei. De asemenea, există filtrul posts_result
.

@David Am verificat în comentariile la întrebare, OP dorește în mod explicit să extindă clasa wp_post
, nu să folosească add_post_meta
.

Știu că aceasta este o postare veche, dar am vrut să împărtășesc o soluție funcțională. Aceasta poate fi realizată făcând:
$posts = get_posts(
array(
"post_type" => $post_type->name,
"numberposts" => -1
)
);
foreach($posts as &$post)
{
$custom_fields = (array)$post;
// adaugă câmp(uri) suplimentar(e) în felul acesta
$custom_fields["posttype_link"] = get_permalink($post->ID);
$post = (object)$custom_fields;
}

Folosește hook-ul the_post: https://developer.wordpress.org/reference/hooks/the_post/
Vei modifica obiectul global $post, așa că nu este nevoie să îl returnezi ca și cum ar fi un filtru. Cei 2 parametri $post și $query sunt transmiși prin referință.
