web-dev-qa-db-ja.com

WP_Postオブジェクトに追加データを追加する

WP_Post として返されるデータに項目を追加したいです。そのため、WP_Postオブジェクトを返すすべての関数/クエリに対して、追加データを追加したいと思います。

返される結果の例:

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
]

例えば、関数 get_post() または get_page_by_path() が実行されると、それらは私の追加データと共にWP_Postオブジェクトを返します。

私は適切な hook/filter を見つけようとしましたが、これは失敗しました。

私は私ができることを願っています:

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

私の考えは、WP_Postオブジェクトを返すさまざまなコア機能を使用するWP用のカスタムAPIを構築する必要があるということです。追加のデータを1か所に追加できると、コードが重複するのを防ぐことができます。

これが十分に明確であることを願っています。どんな助けでも素晴らしいでしょう!

4
Levi Cole

追加のデータが直接投稿メタを参照する場合は、何もする必要はありません。なぜならWP_Postは直接投稿メタキーを要求する"マジック"メソッド __isset() および __get() を実装しているからです。キー:page_templatepost_categorytags_inputおよびancestors)これが動作を示す簡単な例です。

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

それ以外の場合は、フィルタ 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
);

しかし、私はオブジェクト指向のアプローチを使用して、あなたの問題領域に従う独自のエンティティインターフェースを作成することをお勧めします。次に実装はWP_Postインスタンスを依存関係としてラップします。たとえば、 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 );
    }
}

それであなたのビジネスロジックはタイプごとに book の構造に依存することができ、依存性ごとにタイプBookをヒントにします。本のリストを取得するには、最初のステップでWP_Queryをラップするファクトリを実装するか、WP_Query引数を取得して本のインスタンスのリストを返すことができます。その場合、posts_resultsWP_Query::postsインスタンスのリストで置き換えるためにType\Bookフィルタを使用して、WPコア全体で型の一貫性が損なわれないようにする必要があります。

7
David

TLDR;あなたはできません、あなたはすべきではありません。

それは 'final' として定義されているので、追加のフィールドを持つ WP_postクラスを拡張することは不可能 です。おそらくそのクラスを別のクラスにラップすることで回避することができます( tutorial )が、それはまだお勧めできません。

すべての種類のテーマとプラグインは メタデータとして格納されているメタデータ に依存しています。あなたはそれが今はたらくようになるかもしれません、しかし、あなたが使いたい何らかのプラグインがあなたがあなたのメタデータを保存した方法を処理することができないことがわかったとき、おそらく将来それを後悔するでしょう。

1
cjbj