7

I'd like to create a subclass of WP_Post and add some "model functionality" to it. How can i force WP to create objects of that child class instead of WP_Post itself, when i query for my custom post type?

Example:

Let's assume i have two custom post types: Book and Review. Each Book can have many Reviews. On my Book, I want a method to sum up all its reviews. I'd define the following class:

class Book extends WP_Post
{
    public function reviewsSummary()
    {
        // Retrieve all reviews for $this book
        // Sum up their ratings
        // Return that sum
    }
}

Is there a way, for example when calling register_post_type(), to force WordPress into casting all posts of type "book" into my Book class instead of WP_Post?

Could look something like this:

register_post_type('book', [
    …,
    'class' => Acme\Models\Book::class
]);
3
  • I like the idea of asking register_post_type to return you own class instead of the wp_post class. But no that functionality does not exist in the current class. Nov 18, 2016 at 3:55
  • You might want to use a Decorator if you need to extend the functionality or a Proxy if you need to get an layer of abstraction for refactoring and decoupling (not for gaining access to private or protected functions!). You could as well build a factory and some repository where you can return whatever pleases your needs. WP_Post is rarely needed directly in cases where you do not have to rely on checks against a concrete type.
    – kaiser
    Nov 22, 2016 at 21:59
  • Btw people with similar questions might be interested in Timber: timber.github.io/timber
    – jsphpl
    Nov 25, 2016 at 10:27

2 Answers 2

10

WP_Post class in WP is final, so it explicitly forbids subclassing. It is also quite vague in practice, a lot of code around will happily take/produce post–like objects as long as they have established data structure.

It is challenging to recommend an alternative without knowing more about your specific needs. In a general and assuming use in templates the typical would be to create a template tag function that will calculate score for review post, provided to it as argument and/or current in the Loop.

2
5

How to "subclass" WP_Post

Thank you, @Rarst for pointing out the issue that you can't subclass WP_Post, which is a major problem in this case.

Workaround

There is, however, a way of working around it using a wrapper class that has a real WP_Post object stored as an attribute and exposes it via magic methods in order to behave like one.

Two examples of that approach can be found here and here.

Warning: In many cases, this approach might not work for different reasons, one being that these objects won't pass an instanceof WP_Post check.


Where to hook in

So let's assume we could replace WP_Post somehow. The thing i was actually looking for was where to hook in in order to replace WP_Post. The answer to this question is the posts_results filter and was given here: https://stackoverflow.com/a/40631962/3919281

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.