web-dev-qa-db-fra.com

Ajout de données supplémentaires à l'objet WP_Post

Je souhaite ajouter des éléments supplémentaires aux données renvoyées sous la forme WP_Post . Donc, pour chaque fonction/requête qui retourne un objet WP_Post, je veux que mes données supplémentaires soient ajoutées.

Exemple de résultat renvoyé:

WP_Post (object) => [
    // Default data returned by 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,

    // Additional data I want to add
    extra_data_1        => array,
    more_data_key       => string,
    another_added       => string
]

Par exemple, lorsque les fonctions get_post() ou get_page_by_path() sont exécutées, elles renverront l'objet WP_Post avec mes données supplémentaires.

J'ai essayé de trouver le hook/filter approprié mais cela n'a pas abouti.

J'espère pouvoir faire quelque chose comme:

// This is concept code
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;
});

Mon raisonnement est que je dois créer une API personnalisée pour WP qui utilise une gamme de fonctions principales différentes qui renvoient des objets WP_Post. Pouvoir ajouter mes données supplémentaires à un endroit m'empêcherait de dupliquer du code.

J'espère que c'est assez clair. Toute aide est la bienvenue!

4
Levi Cole

Si vos données supplémentaires font directement référence à une méta de publication, vous n'avez rien à faire, car WP_Post implémente les méthodes "magic" __isset() et __get() qui demande directement des clés de méta de publication (à l'exception des quatre suivantes). clés: page_template, post_category, tags_input et ancestors). Voici un exemple rapide qui montre le comportement:

<?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']

Dans les autres cas, utilisez le filtre 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' );
            // and so on …
        }

        return $posts;
    },
    10,
    2
);

Cependant, je suggérerais d'utiliser une approche orientée objet et de créer ses propres interfaces d'entité, qui suivent votre domaine de problèmes. Les implémentations encapsulent ensuite les instances WP_Post en tant que dépendance. Par exemple, supposons que vous ayez affaire à books :

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

Votre logique métier peut alors s'appuyer sur la structure d'un indicateur book by type pour indiquer le type Book à chaque dépendance. Pour récupérer une liste de livres, vous pouvez implémenter une fabrique dans la première étape, qui encapsule un WP_Query ou récupère les arguments WP_Query et renvoie une liste d'instances de livre. Dans ce cas, vous ne devez pas utiliser le filtre posts_results pour remplacer WP_Query::posts par une liste d'instances Type\Book afin de ne pas compromettre la cohérence des types dans WP core.

7
David

TLDR; Vous ne pouvez pas et vous ne devriez pas.

Il est impossible d'étendre la WP_post classe avec des champs supplémentaires, car elle a été définie comme 'final' . Vous pourriez peut-être contourner cela en regroupant la classe dans une autre classe ( tutorial ), mais ce n'est toujours pas conseillé.

Toutes sortes de thèmes et de plugins reposent sur le stockage des métadonnées sous la forme de métadonnées . Vous pouvez le faire fonctionner maintenant, mais vous le regretterez probablement à l'avenir, lorsque vous découvrirez qu'un plug-in que vous souhaitez utiliser ne peut pas gérer la façon dont vous avez stocké vos métadonnées.

1
cjbj