web-dev-qa-db-de.com

Hinzufügen zusätzlicher Daten zum WP_Post-Objekt

Ich möchte den als WP_Post zurückgegebenen Daten zusätzliche Elemente hinzufügen. Für jede Funktion/Abfrage, die ein WP_Post-Objekt zurückgibt, möchte ich meine zusätzlichen Daten hinzufügen.

Beispiel für das zurückgegebene Ergebnis:

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
]

Wenn zum Beispiel die Funktionen get_post() oder get_page_by_path() ausgeführt werden, geben sie das WP_Post-Objekt zusammen mit meinen zusätzlichen Daten zurück.

Ich habe versucht, den passenden Haken/Filter zu finden, aber dies war nicht erfolgreich.

Ich hoffe, ich kann etwas machen wie:

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

Ich muss eine benutzerdefinierte API für WP erstellen, die eine Reihe verschiedener Kernfunktionen verwendet, die WP_Post-Objekte zurückgeben. Wenn ich meine zusätzlichen Daten an einer Stelle hinzufügen kann, kann ich den Code nicht duplizieren.

Ich hoffe das ist klar genug. Jede Hilfe wäre toll!

4
Levi Cole

Wenn Ihre zusätzlichen Daten direkt auf ein Post - Meta verweisen, müssen Sie nichts unternehmen, da WP_Post die "magic" - Methoden __isset() und __get() implementiert, die direkt nach Post - Meta - Schlüsseln fragen (mit Ausnahme der folgenden vier) Schlüssel: page_template, post_category, tags_input und ancestors). Hier ist ein kurzes Beispiel, das das Verhalten zeigt:

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

Verwenden Sie in jedem anderen Fall den Filter 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
);

Ich würde jedoch vorschlagen, einen objektorientierten Ansatz zu verwenden und eigene Entitätsschnittstellen zu erstellen, die Ihrer Problemdomäne folgen. Die Implementierungen schließen dann WP_Post -Instanzen als Abhängigkeit ein. Nehmen wir zum Beispiel an, Sie haben es mit books zu tun:

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

Ihre Geschäftslogik kann sich dann auf die Struktur eines book by type stützen und den Typ Book für jede Abhängigkeit angeben. Um eine Liste von Büchern abzurufen, können Sie im ersten Schritt eine Factory implementieren, die einen WP_Query umschließt, oder WP_Query-Argumente abrufen und eine Liste von Buchinstanzen zurückgeben. In diesem Fall sollten Sie den posts_results-Filter nicht verwenden, um WP_Query::posts durch eine Liste von Type\Book-Instanzen zu ersetzen, damit die Typenkonsistenz nicht im gesamten WP Core unterbrochen wird.

7
David

TLDR; Du kannst nicht und du solltest nicht.

Es ist unmöglich, die Klasse WP_post mit zusätzlichen Feldern zu erweitern, da sie als 'final' definiert wurde. Sie könnten das vielleicht umgehen, indem Sie die Klasse in eine andere Klasse einbinden ( Tutorial ), aber es ist immer noch nicht ratsam.

Alle Arten von Designs und Plugins basieren auf den Metadaten, die als Metadaten gespeichert werden . Sie können es jetzt zum Laufen bringen, aber Sie werden es wahrscheinlich in Zukunft bereuen, wenn Sie feststellen, dass einige Plugins, die Sie verwenden möchten, nicht mit der Art und Weise umgehen können, in der Sie Ihre Metadaten gespeichert haben.

1
cjbj