Aggiungere dati aggiuntivi all'oggetto WP_Post

21 set 2016, 12:58:14
Visualizzazioni: 13.9K
Voti: 7

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!

7
Commenti

C'è un motivo per cui non vuoi usare post_meta?

cjbj cjbj
21 set 2016 13:13:03

@cjbj Ho già applicato i post meta agli articoli, ma l'oggetto WP_Post non li include di default. Ho aggiornato la mia domanda per evitare confusione. Il mio ragionamento è che sto creando un'API personalizzata per WP che utilizza diverse funzioni core che restituiscono oggetti WP_Post. Poter aggiungere i miei dati aggiuntivi in un unico punto mi eviterebbe di duplicare il codice.

Levi Cole Levi Cole
21 set 2016 13:21:53

Ho capito il tuo punto. Cancellerò la mia risposta. Ho appena controllato post.php e class-wp-post e non ho trovato un singolo action hook o filter hook. Questa è una brutta notizia per l'idea che stai cercando di realizzare qui.

Ahmed Fouad Ahmed Fouad
21 set 2016 13:23:29

Per evitare di duplicare il codice, perché non scrivere le tue funzioni wrapper che restituiscono valori sia dall'oggetto post che dai suoi metadati? Sembra un approccio più semplice.

Andy Macaulay-Brook Andy Macaulay-Brook
21 set 2016 13:49:10

@AndyMacaulay-Brook Attualmente lo sto facendo in questo modo, ma mi chiedevo se esistesse una soluzione migliore.

Levi Cole Levi Cole
21 set 2016 13:50:57

Dipende da come definisci "migliore" :-) Secondo me una soluzione che ti fornisce le funzioni di cui hai bisogno senza modificare gli interni di WP sembra piuttosto buona. Esistono già funzioni per ottenere un campo del post e un campo meta del post, quindi incapsularle con mezza dozzina di righe di codice è veloce e semplice, non rompe nient'altro e utilizzerà anche qualsiasi cache che le funzioni integrate già implementano.

Andy Macaulay-Brook Andy Macaulay-Brook
21 set 2016 13:54:42

In teoria si potrebbe usare l'hook the_post per aggiungere proprietà aggiuntive. Se sia opportuno farlo è però decisamente discutibile.

Howdy_McGee Howdy_McGee
7 gen 2021 17:17:22
Mostra i restanti 2 commenti
Tutte le risposte alla domanda 4
0
11

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.

21 set 2016 13:37:26
3

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.

21 set 2016 13:36:47
Commenti

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 David
21 set 2016 13:43:16

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

cjbj cjbj
21 set 2016 13:46:31

Da quello che vedo, vuole estendere gli oggetti post, non la dichiarazione della classe.

David David
21 set 2016 13:53:23
0

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;
}
7 gen 2021 15:36:38
0

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.

26 ago 2021 00:02:54