Aggiungere dati aggiuntivi all'oggetto WP_Post
Voglio aggiungere elementi aggiuntivi ai dati restituiti come WP_Post
. Quindi per ogni funzione/query che restituisce un oggetto WP_Post voglio che vengano inclusi i miei dati aggiuntivi.
Esempio di risultato restituito:
WP_Post (object) => [
// Dati predefiniti restituiti da 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,
// Dati aggiuntivi che voglio includere
extra_data_1 => array,
more_data_key => string,
another_added => string
]
Ad esempio, quando vengono eseguite le funzioni get_post()
o get_page_by_path()
, queste dovrebbero restituire l'oggetto WP_Post insieme ai miei dati aggiuntivi.
Ho provato a trovare l'appropriato hook/filter ma senza successo.
Speravo di poter fare qualcosa come:
// Questo è codice concettuale
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;
});
Il mio ragionamento è che sto costruendo un'API personalizzata per WordPress che utilizza diverse funzioni core che restituiscono oggetti WP_Post. Poter aggiungere i miei dati aggiuntivi in un unico punto eviterebbe la duplicazione del codice.
Spero che sia abbastanza chiaro. Qualsiasi aiuto sarebbe fantastico!
Se i tuoi dati extra fanno riferimento direttamente a una post meta, non devi fare nulla, perché WP_Post
implementa i metodi »magici« __isset()
e __get()
che interrogano direttamente le chiavi delle post meta (eccetto per le seguenti quattro chiavi: page_template
, post_category
, tags_input
e ancestors
). Ecco un rapido esempio che mostra il comportamento:
<?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']
In qualsiasi altro caso, utilizza il filtro 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' );
// e così via …
}
return $posts;
},
10,
2
);
Tuttavia, suggerirei di utilizzare un approccio orientato agli oggetti e creare interfacce di entità personalizzate, che seguano il tuo dominio del problema. Le implementazioni poi incapsulano istanze di WP_Post
come dipendenza. Ad esempio, supponiamo che tu abbia a che fare con libri:
<?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 );
}
}
La tua logica di business può quindi fare affidamento sulla struttura di un libro utilizzando il type hint del tipo Book
per ogni dipendenza. Per recuperare un elenco di libri, potresti implementare una factory in un primo momento che incapsuli un WP_Query
o recuperi argomenti di WP_Query e restituisca un elenco di istanze di libri. Non dovresti utilizzare il filtro posts_results
in quel caso per sostituire WP_Query::posts
con un elenco di istanze di Type\Book
per non rompere la coerenza dei tipi all'interno del core di WP.

TLDR; Non puoi e non dovresti.
È impossibile estendere la classe WP_post
con campi extra, perché è stata definita come 'final'. Potresti aggirare il problema incapsulando la classe in un'altra classe (tutorial), ma comunque non è consigliabile.
Tutti i tipi di temi e plugin si basano sul fatto che i metadati siano memorizzati come metadati. Potresti riuscire a farlo funzionare ora, ma probabilmente te ne pentirai in futuro, quando scoprirai che qualche plugin che vuoi usare non è in grado di gestire il modo in cui hai memorizzato i tuoi metadati.

Vuole solo aggiungere proprietà pubbliche a un oggetto arbitrario. Questo è possibile indipendentemente dall'estendibilità della dichiarazione della classe. Inoltre c'è il filtro posts_result
.

@David Ho verificato nei commenti alla domanda, OP vuole esplicitamente estendere la classe wp_post
, non usare add_post_meta
.

So che questo è un post vecchio ma ho pensato di condividere una soluzione funzionante Si può ottenere facendo:
$posts = get_posts(
array(
"post_type" => $post_type->name,
"numberposts" => -1
)
);
foreach($posts as &$post)
{
$custom_fields = (array)$post;
// aggiungi campo(i) extra in questo modo
$custom_fields["posttype_link"] = get_permalink($post->ID);
$post = (object)$custom_fields;
}

Utilizza l'hook the_post: https://developer.wordpress.org/reference/hooks/the_post/
Andrai a modificare l'oggetto globale $post quindi non è necessario restituirlo come se fosse un filtro. I 2 parametri $post e $query vengono passati per riferimento.
