Make WordPress Core

Opened 8 years ago

Closed 6 years ago

#34875 closed enhancement (duplicate)

Allow developers to use an extended version of WP_Post (also WP_Term & WP_Comment)

Reported by: flixos90's profile flixos90 Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.4
Component: Posts, Post Types Keywords:
Focuses: Cc:

Description

A lot of times, developers use their own classes to work with post objects (or term or comment objects). In the rest of this ticket, I am only going to refer to WP_Post, but the other two classes are similar here.

Right now, using a custom class is only possible by basically wrapping a WP_Post object with it. If for example a theme does this, it usually results in creating an instance of that class in almost every theme template file related to posts. It would be a much better development workflow to be able to

  • actually extend the WP_Post class instead of wrapping it and
  • do it in the get_post() function so that it happens everywhere

So this ticket probably addresses two issues which however are closely related to each other. I saw that my first point has already been discussed in #24672 a while back. Now that we have WP_Term and WP_Comment in the upcoming 4.4 release, it might be worth reconsidering it, as @nacin describes in the ticket.

If we realize the first point above, we could also consider doing the second since this change would actually make the whole thing much more useful. If we can used an extended version of WP_Post, we could have custom classes tailored to the more special needs of certain custom post types etc. This would obviously require a deep change in WordPress where developers would be able to replace the default WP_Post class with their own subclass of it. Below you can find a code snippet of how that could look like (only has the get_post() function, the code in the class itself would of course need to be adjusted too):

<?php
function get_post( $post = null, $output = OBJECT, $filter = 'raw' ) {
        if ( empty( $post ) && isset( $GLOBALS['post'] ) )
                $post = $GLOBALS['post'];

        $post_class_name = apply_filters( 'wp_post_class_name', 'WP_Post', $post );
        if ( 'WP_Post' !== $post_class_name && ( ! class_exists( $post_class_name ) || ! is_subclass_of( $post_class_name, 'WP_Post' ) ) ) {
                _doing_it_wrong( __FUNCTION__, sprintf( __( 'The class %s is not a valid PHP class for a post object.' ), $post_class_name ), '4.5.0' );
                $post_class_name = 'WP_Post';
        }

        if ( $post instanceof WP_Post ) {
                $_post = $post;
        } elseif ( is_object( $post ) ) {
                if ( empty( $post->filter ) ) {
                        $_post = sanitize_post( $post, 'raw' );
                        $_post = new $post_class_name( $_post );
                } elseif ( 'raw' == $post->filter ) {
                        $_post = new $post_class_name( $post );
                } else {
                        $_post = WP_Post::get_instance( $post->ID );
                }
        } else {
                $_post = WP_Post::get_instance( $post );
        }

        if ( ! $_post )
                return null;

        $_post = $_post->filter( $filter );

        if ( $output == ARRAY_A )
                return $_post->to_array();
        elseif ( $output == ARRAY_N )
                return array_values( $_post->to_array() );

        return $_post;
}

While this is a deep change, I think it would benefit the workflow of a lot of developers. Let's discuss.

Change History (6)

#1 follow-ups: @nacin
8 years ago

I think I'm still against this. I'd like to see us start to add methods to these functions. If others are allowed to extend WP_Post et al., core will end up breaking their code, and I don't think core should take on this responsibility right now.

#2 in reply to: ↑ 1 @boonebgorges
8 years ago

Replying to nacin:

I think I'm still against this. I'd like to see us start to add methods to these functions. If others are allowed to extend WP_Post et al., core will end up breaking their code, and I don't think core should take on this responsibility right now.

Also, we should be encouraging dependency injection with stable interfaces rather than extending classes.

#3 in reply to: ↑ 1 @flixos90
8 years ago

@nacin:

I'd like to see us start to add methods to these functions.

I'm not sure what you mean. Could you elaborate a little?

@boonebgorges:

Also, we should be encouraging dependency injection with stable interfaces rather than extending classes.

That sounds like a solid alternative. Do you know of any resources on it that are already out there? In particular, do you have a specific approach to it?

#4 follow-up: @flixos90
8 years ago

It's been a while, but I was just wondering about introducing a filter in get_post(). It could be related to this functionality, but could be used in other ways too. Looking at get_term(), get_comment(), get_site() and get_network(), all these functions include a filter of the same name. get_post() is the only exception here.

I still think it would be a valuable enhancement for developers to use their own post classes based on WP_Post. This would not make sense in a plugin, but in various custom projects where one has full control over the environment. Many use wrapper classes for posts with their own functionality, but it's a pain to do so. Writing your own post class derived from WP_Post and using a filter get_post to transform the object accordingly would make it a lot easier.

#5 in reply to: ↑ 4 @ocean90
8 years ago

Replying to flixos90:

It's been a while, but I was just wondering about introducing a filter in get_post().

See #30292 and #12955.

#6 @flixos90
6 years ago

  • Milestone Awaiting Review deleted
  • Resolution set to duplicate
  • Status changed from new to closed

Closing in favor of #12955 which has more history on this topic.

Note: See TracTickets for help on using tickets.