Adăugarea de date suplimentare la obiectul WP_Post

21 sept. 2016, 12:58:14
Vizualizări: 13.9K
Voturi: 7

Doresc să adaug elemente suplimentare la datele returnate ca WP_Post. Astfel, pentru fiecare funcție/interogare care returnează un obiect WP_Post, vreau ca datele mele suplimentare să fie incluse.

Exemplu de rezultat returnat:

WP_Post (object) => [
    // Date standard returnate de 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,

    // Date suplimentare pe care vreau să le adaug
    extra_data_1        => array,
    more_data_key       => string,
    another_added       => string
]

De exemplu, când funcțiile get_post() sau get_page_by_path() sunt executate, acestea vor returna obiectul WP_Post împreună cu datele mele suplimentare.

Am încercat să găsesc hook-ul/filtrul potrivit, dar fără succes.

Sper că pot face ceva de genul:

// Acesta este cod conceptual
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;
});

Motivația mea este că trebuie să construiesc un API personalizat pentru WP care folosește diverse funcții native care returnează obiecte WP_Post. Posibilitatea de a adăuga datele mele suplimentare într-un singur loc m-ar scuti de duplicarea codului.

Sper că am fost suficient de clar. Orice ajutor ar fi minunat!

7
Comentarii

Există vreun motiv pentru care nu dorești să folosești post_meta?

cjbj cjbj
21 sept. 2016 13:13:03

@cjbj Am aplicat post meta postărilor, dar obiectul WP_Post nu include acest lucru în mod implicit. Am actualizat întrebarea mea pentru a evita confuzia. Motivul meu este că trebuie să construiesc un API personalizat pentru WP care utilizează o gamă de funcții de bază diferite care returnează obiecte WP_Post. Abilitatea de a adăuga datele mele suplimentare într-un singur loc m-ar scuti de a duplica codul.

Levi Cole Levi Cole
21 sept. 2016 13:21:53

Am înțeles punctul tău. Voi șterge răspunsul meu. Tocmai am parcurs post.php și class-wp-post și nu am găsit niciun action hook sau filter hook. Asta e o veste proastă pentru ideea pe care încerci să o realizezi aici.

Ahmed Fouad Ahmed Fouad
21 sept. 2016 13:23:29

Pentru a preveni duplicarea codului, de ce nu îți scrii propriile funcții wrapper care returnează valori atât din obiectul post, cât și din metadatele acestuia? Pare o abordare mai simplă.

Andy Macaulay-Brook Andy Macaulay-Brook
21 sept. 2016 13:49:10

@AndyMacaulay-Brook Acesta este modul în care fac acum, dar mă întrebam dacă există o soluție mai bună.

Levi Cole Levi Cole
21 sept. 2016 13:50:57

Depinde cum definești "mai bun" :-) În opinia mea, o soluție care îți oferă funcțiile de care ai nevoie fără să interfereze cu mecanismele interne ale WP pare destul de bună. Există deja funcții pentru a obține un câmp din post și un câmp de metadate, așa că învelirea acestora cu câteva linii de cod este rapidă și ușoară, nu strică nimic și va folosi de asemenea orice mecanism de caching pe care îl au deja funcțiile încorporate.

Andy Macaulay-Brook Andy Macaulay-Brook
21 sept. 2016 13:54:42

Teoretic, cineva ar putea folosi the_post hook pentru a adăuga proprietăți suplimentare. Dar dacă ar trebui să faci asta este cu siguranță dezbătut.

Howdy_McGee Howdy_McGee
7 ian. 2021 17:17:22
Arată celelalte 2 comentarii
Toate răspunsurile la întrebare 4
0
11

Dacă datele tale suplimentare fac referire directă la o meta-informație a postării, nu trebuie să faci nimic, deoarece WP_Post implementează metodele »magice« __isset() și __get() care interoghează direct cheile meta ale postării (cu excepția următoarelor patru chei: page_template, post_category, tags_input și ancestors). Iată un exemplu rapid care arată comportamentul:

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

În orice alt caz, folosește filtrul 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' );
            // și așa mai departe …
        }

        return $posts;
    },
    10,
    2
);

Totuși, aș sugera să folosești o abordare orientată pe obiecte și să creezi propriile interfețe de entități, care să urmeze domeniul tău de problemă. Implementările vor înfășura apoi instanțele WP_Post ca o dependență. De exemplu, să presupunem că lucrezi cu cărți:

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

Logica ta de afaceri poate apoi să se bazeze pe structura unei cărți prin indicarea tipului Book la fiecare dependență. Pentru a obține o listă de cărți, poți implementa o fabrică într-un prim pas care să înfășureze un WP_Query sau să preia argumente WP_Query și să returneze o listă de instanțe de cărți. Nu ar trebui să folosești filtrul posts_results în acest caz pentru a înlocui WP_Query::posts cu o listă de instanțe Type\Book pentru a nu strica consistența tipului în întregul nucleu WP.

21 sept. 2016 13:37:26
3

TLDR; Nu poți și nici nu ar trebui.

Este imposibil să extinzi clasa WP_post cu câmpuri suplimentare, deoarece a fost definită ca 'final'. Poate ai putea ocoli acest lucru prin încapsularea clasei într-o altă clasă (tutorial), dar tot nu este recomandat.

Toate tipurile de teme și plugin-uri se bazează pe faptul că metadatele sunt stocate ca metadate. Poate reuși să funcționeze acum, dar vei regreta probabil în viitor, când vei descoperi că un plugin pe care dorești să-l folosești nu poate gestiona modul în care ai stocat metadatele.

21 sept. 2016 13:36:47
Comentarii

El vrea doar să adauge proprietăți publice la un obiect arbitrar. Acest lucru este posibil indiferent de extensibilitatea declarației clasei. De asemenea, există filtrul posts_result.

David David
21 sept. 2016 13:43:16

@David Am verificat în comentariile la întrebare, OP dorește în mod explicit să extindă clasa wp_post, nu să folosească add_post_meta.

cjbj cjbj
21 sept. 2016 13:46:31

Din ceea ce înțeleg, el/ea vrea să extindă obiectele post, nu declarația clasei.

David David
21 sept. 2016 13:53:23
0

Știu că aceasta este o postare veche, dar am vrut să împărtășesc o soluție funcțională. Aceasta poate fi realizată făcând:

$posts = get_posts( 
    array(
        "post_type" => $post_type->name,
        "numberposts" => -1 
    )
);
foreach($posts as &$post)
{
    $custom_fields = (array)$post;
    // adaugă câmp(uri) suplimentar(e) în felul acesta
    $custom_fields["posttype_link"] = get_permalink($post->ID);
    $post = (object)$custom_fields;
}
7 ian. 2021 15:36:38
0

Folosește hook-ul the_post: https://developer.wordpress.org/reference/hooks/the_post/

Vei modifica obiectul global $post, așa că nu este nevoie să îl returnezi ca și cum ar fi un filtru. Cei 2 parametri $post și $query sunt transmiși prin referință.

26 aug. 2021 00:02:54