将其他数据添加到WP_Post对象

时间:2016-09-21 作者:Levi Cole

我想在返回的数据中添加其他项WP_Post. 因此,对于每个返回WP\\u 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\\u 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构建一个自定义API,该API使用一系列不同的核心函数来返回WP\\U Post对象。能够在一个地方添加额外的数据可以防止我复制代码。

我希望这足够清楚。任何帮助都会很好!

4 个回复
SO网友:David

如果您的额外数据直接引用post meta,则无需执行任何操作,因为WP_Post 实现»magic«方法__isset()__get() 它直接要求post meta键(以下四个键除外:page_template, post_category, tags_inputancestors). 下面是一个快速示例,展示了该行为:

<?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 实例作为依赖项。例如,假设您正在处理书籍:

<?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 在每个依赖项上。要获取书籍列表,您可以在第一步中实现一个工厂,该工厂将WP_Query 或获取WP\\u查询参数并返回book实例列表。您不应该使用posts_results 在这种情况下要更换的过滤器WP_Query::posts 包含以下列表:Type\\Book 实例不破坏整个WP核心的类型一致性。

SO网友:cjbj

太长,读不下去了你不能也不应该。

是的impossible to extend the WP_post class 具有额外字段,因为它已定义为\'final\'. 您可能可以通过将该类包装到另一个类中来绕过此问题(tutorial), 但这仍然是不可取的。

所有类型的主题和插件都依赖于metadata being stored as metadata. 您可能现在就可以使用它,但将来您可能会后悔,因为您发现您想要使用的某个插件无法处理您存储元数据的方式。

SO网友:Mark Rutten

我知道这是一个老帖子,但思想共享一个工作解决方案这可以通过以下方式实现:

$posts = get_posts( 
    array(
        "post_type" => $post_type->name,
        "numberposts" => -1 
    )
);
foreach($posts as &$post)
{
    $custom_fields = (array)$post;
    // add extra field(s) like this
    $custom_fields["posttype_link"] = get_permalink($post->ID);
    $post = (object)$custom_fields;
}

SO网友:noahmason

使用the_post 钩子:https://developer.wordpress.org/reference/hooks/the_post/

您将修改全局$post 对象,因此无需像返回过滤器一样返回它。2个参数$post$query 传递以供参考。

相关推荐

如果有新数据,则使用wp_cron和wp_mail发送电子邮件警报(外部API)-伪代码

我想每天检查两次是否发布了一些新数据,如果是这样的话,请给我发一封电子邮件。在这里的伪代码中,我认为我可以做到:获取新电影列表(外部API请求)获取旧电影列表(在某处存储,但如何存储?)</比较两个列表发送电子邮件和wp\\U邮件,下次更新旧列表的内容(如何?)</每天用wp\\u cron重复这一过程两次我的问题是,我不知道如何以及在哪里存储以前的电影列表?我曾想过可以在函数中调用一个全局变量,但从目前为止的情况来看,似乎最好避免使用全局变量?另外,我不知道是否可以为下一个任务更新全局变量。