#26877 closed enhancement (duplicate)
Allow get_post() to accept a custom post object instead of only WP_Post
Reported by: | MikeSchinkel | Owned by: | |
---|---|---|---|
Milestone: | Priority: | normal | |
Severity: | normal | Version: | |
Component: | Posts, Post Types | Keywords: | |
Focuses: | Cc: |
Description
I'm refactoring a poorly coded theme that I want to use for it's design and I am finding it very helpful to be able to create a theme-specific Post class that encapsulates theme-specific behaviors related to Posts that the theme currently has "littered" over many different templates. (I usually build plugins and (almost?) never build themes but it seems this would be useful when building themes too.)
So I created a class that looks like this for my refactoring efforts (the following is only a small segment of the class but I've only included the relevant portions for this ticket):
/** * Class MyTheme_Post */ class MyTheme_Post { private $_post; private $_post_stack = array(); /** * @param int|WP_Post $post */ function __construct( $post ) { if ( is_numeric( $post ) ) { $post = get_post( $post ); } $this->_post = $post; } /** * Get the title by using the_title() function. * * @param string $before * @param string $after * * @return string */ function title( $before = '', $after = '' ) { $this->_push_post(); $title = the_title( $before, $after, false ); $this->_pop_post(); return $title; } /** * Set global $post to contain the inner WP_Post and push the prior onto an internal stack. * We need this so that get_post() will work correctly. */ function _push_post() { global $post; array_push( $this->_post_stack, $post ); $post = $this->_post; } /** * Pop the prior post off the internal stack. * We need this so that get_post() will work correctly. */ function _pop_post() { global $post; $post = array_pop( $this->_post_stack ); } /** * Delegate any property requests to the contained post. * * @param string $property * * @return array|mixed */ function __get( $property ) { return $this->_post->$property; } }
And then at the top of my theme template I do the following:
$post = new MyTheme_Post( $post );
This works brilliantly except unfortunately whenever get_post()
is called by any template tag or other function, and lots of functions call it; get_post()
throws away the custom instance and creates a new instance of WP_Post
for use instead. You see how I get around this in $post->title()
above, but I can't always do that.
I can envision two (2) fixes for this:
- Remove
final
from theWP_Post
class so I can really subclass it, or - Have
get_post()
inspect a special property (maybe$post->is_custom
) and if it's set totrue
then assume it's an object the developer wants to keep.
I know that subclassing was not wanted for WP_Post when it was being implemented so if that's still the case I'm hoping we could at least do option 2.
Patch attached.
Attachments (3)
Change History (11)
#1
@
11 years ago
- Milestone changed from Awaiting Review to Future Release
Just ran into a very similar use-case. #24672 looks related to me. I suspect we need to:
- Finish classes for the other WordPress objects.
- Remove the
final
fromWP_Post
et all so they can be properly subclassed. - Allow
WP_Query
and similar to return subclass instances.
#2
follow-up:
↓ 3
@
11 years ago
This isn't very convincing, and wasn't on the other ticket you pasted the same code example. You want to subclass a model so that you can use a theme function on one of the global $post
's properties? Is this really worth 2 separate tickets?
#3
in reply to:
↑ 2
@
11 years ago
Replying to wonderboymusic:
This isn't very convincing, and wasn't on the other ticket you pasted the same code example.
Is this really worth 2 separate tickets?
I assume you are replying to me, the OP? If yes, what other ticket are you talking about? In my memory I only posted this one ticket on this topic.
You want to subclass a model so that you can use a theme function on one of the global
$post
's properties?
I don't understand what you mean by "use a theme function"; Are you saying that because I chose title()
as the one methods I showed (vs. one of the other 25+ methods in my actual class) that I am "using a theme function?" If yes, note that rather than overwhelm the reader I was trying to show the smallest example I could, and yes $post->title()
is not that beneficial. But $post->the_video_embed()
, $post->the_featured_image()
and $post->do_show_excerpt()
might help you visualize it better.
What I want to do is be able to add properties and behavior to the $post
object so that when I pass the $post
object around, especially through other people's code that the properties and behavior follow along with it. This is just OOP 101 and wasn't something I though needed to be made highly convincing.
I understand and appreciate @nacin's reluctance to remove final which is why my patch did not propose final
but instead used containment. The problem is we can't use containment if all the methods that would work with posts throw away our instances when they call get_post()
which is the reason for my proposal.
If someone wants to add their own functionality like this they can't do it compatibly with WordPress; they have to write a fully custom theme vs. just add their own selected theme template files.
#4
@
10 years ago
This would have been really useful to me on a recent client project that needed a number of custom post types with additional methods and properties (e.g an event post object with $event_post->get_start_date()
/ $event_post->get_next_occurrence()
methods etc). I resorted to a similar workaround as the OP, but had the same problem of getting get_post
to accept the new object.
Ideally, I would love to see this included in 4.1 with #12955 which would allow a single, universal place to filter or replace post objects with custom classes.
#5
@
9 years ago
- Keywords 2nd-opinion added
Added a patch with a different approach that has a 'get_custom_post_object'
filter in get_post()
.
Patch to allow get_post() to check for is_custom property