Make WordPress Core

Opened 4 years ago

Closed 2 years ago

Last modified 2 years ago

#18950 closed defect (bug) (invalid)

get_post_types() does not return post-types registered with verbose alternatives of the $public argument

Reported by: fireproofsocks Owned by:
Milestone: Priority: normal
Severity: normal Version: 3.2.1
Component: Posts, Post Types Keywords:
Focuses: Cc:


The $public argument for the register_post_type() function is supposedly an alternative for setting the arguments for publicly_queriable, show_ui, show_in_nav_menus, and exclude_from_search; It's true that setting the public argument does cause these other values to be set, but if you then use get_post_types() to query for public post-types, WP does not recognize the equivalence between setting the public option or verbosely setting the others.

To Reproduce:

Enter the following code into a plugin:

function testing() {
 $args => array(
   'publicly_queriable' => true,
   'show_ui' => true,
   'show_in_nav_menus'  => true,
   'exclude_from_search => false
 register_post_type('my_custom_post_type', $args);

add_action('init', 'testing');

In a theme file (or somewhere after the init event):

$pts = get_post_types( array('public'=>true, '_builtin'=>false) );

print_r($pts); // <-- empty!

Expected Result

I would expect the get_post_types() function to return the my_custom_post_type post-type because it is using the equivalent of the $public argument.

Actual Result

No post-types are returned.

This represents a problem: other plugins that interact with post-types often rely on the $public argument when using the get_post_types() function, so any plugin that attempts to verbosely set component attributes will not be recognized. This effectively breaks the API and trainwrecks the interconnectedness of the post-types.

See Also

See forum post: http://wordpress.org/support/topic/public-attribute-for-register_post_type?replies=5#post-2391689

WordPress 3.2.1
PHP 5.3.2

Change History (14)

comment:1 @fireproofsocks4 years ago

Whoops: typo in the $args ('=' not '=>') sorry.

 $args = array(
   'publicly_queriable' => true,
   'show_ui' => true,
   'show_in_nav_menus'  => true,
   'exclude_from_search => false

comment:2 @knutsp4 years ago

  • Cc knut@… added

comment:3 @Big Bagel4 years ago

  • Cc bigbagel@… added

This really isn't a defect since everything is working as it should.

$publicly_queriable, $show_ui, $show_in_nav_menus, and $exclude_from_search, if not explicitly set, have their default values based on $public. This doesn't mean $public is simply a shortcut for the others. There isn't and there shouldn't be any "equivalence" between setting $public and the other four. If there were, what would happen if someone wanted to do this:

$args => array(
    'public' => false,
    'publicly_queriable' => true,
    'show_ui' => true,
    'show_in_nav_menus' => true,
    'exclude_from_search => false
 register_post_type( 'my_custom_post_type', $args );

For example, I currently use a plugin that registers a new post type with these arguments:

$args => array(
    'public' => true,
    'show_ui' => false,
    'show_in_nav_menus' => false

$public defaults to false and leaving it out will obviously result in the newly registered post type being excluded from the returned array when get_post_types() is explicitly told to return only those with $public set to true. If you want your post type to be returned when someone uses:

get_post_types( array( 'public' => true, '_builtin' => false ) );

Just make sure to set $public to true:

$args => array(
    'public' => true,
    'publicly_queriable' => true,
    'show_ui' => true,
    'show_in_nav_menus' => true,
    'exclude_from_search => false
 register_post_type( 'my_custom_post_type', $args );

Now, in respect to this as an enhancement/feature request, altering register_post_type() or get_post_types() to use $public as only a shortcut for the other four arguments would mean breaking or causing unexpected results for any code that already makes use of these functions while restricting the possibility of certain configurations (such as in my first two examples). Since I don't see any valid reason to break code simply because the purpose and proper use of the $public argument was misunderstood, I would suggest resolving this as wontfix or invalid.

comment:4 @doodlebee3 years ago

  • Version changed from 3.2.1 to 3.4.1

I just wanted to add that I am using WordPress 3.4.1, and I have my custom post types registered with

'public' => true


get_post_types( array( 'public' => true, '_builtin' => false ) );

returns an empty array every time.

I've also added

'show_ui' => true,
'publicly_queryable' => true, 
'public' => true,

(with and without the "public" setting in there) to my post type registration, and the array returned is empty, no matter what I use within get_post_types(). Custom post types are never returned.

comment:5 @markoheijnen3 years ago

  • Keywords close added

@doodlebee: You shouldn't change the version because you experience it. The version is ment when the bug could have been started.
I'm curious how you registered your post type since all the WordPress code that also uses get_post_types() does work.

The reason Big Bagel is correct. When you register a post type the default public value is false. I mark this as close since it isn't really something to fix.

comment:6 @fireproofsocks3 years ago

The problem is that WP does not recognize the equivalence of its arguments, not the default values for them. @doodlebee may have registered post types incorrectly, but the problem remains. By marking this closed, you are essentially saying that the "public" attribute is its own self-sufficient attribute and is not a short-hand notation for setting other attributes. Since none of the post-type functionality follows unique behavior for the public attribute and it is instead used as a convenience argument for querying post-types, I don't see how you can architecturally justify the public attribute as being self-standing in this way.

comment:7 @markoheijnen3 years ago

The public argument is not equal to other arguments. So yes I think it its own self attribute. When you do set that argument others will start with another default value what can be overridden if the argument has been set. It would be weird the other way aroung when setting the show_ui argument to true will mean you can view the post online.

If you look at this ticket #20164 you can see why query on the public argument is wrong and it should have been the show_ui argument.

comment:8 @SergeyBiryukov3 years ago

  • Keywords 2nd-opinion added
  • Version changed from 3.4.1 to 3.2.1

comment:9 @fireproofsocks3 years ago

Sounds like you're confusing show_ui and publicly_queryable. Here's my understanding of all these attributes:

  • show_ui: the post-type will be visible in the WP admin interface (hard to imagine a case where you wouldn't set this to true)
  • publicly_queryable: visible on the front-end via a request. I.e. ANY request.
  • exclude_from_search: controls whether posts in this post-type show up in search results.
  • has_archive: whether posts of this post-type show up in archives.

So the "public" attribute here remains vague. Even if we add more attributes to define even more behavior (e.g. show in RSS feed, etc.), everything I've seen about the topic means that YES, when people query on the public argument, YES they SHOULD have queried on a different attribute, but I think most of the time, they probably meant publicly_queryable.

So that's EXACTLY the problem: people are just blindly searching for "public" post-types and they don't necessarily know what they mean. So that's why I filed this in the first place: so if smarter folks query on publicly_queryable, then the query will return post-types that were registered using the short-hand "public" attribute and VICE VERSA: if smarter folks registered their post-types verbosely with all attributes, then a simpler query searching for the vague "public" post-types would also pull up post-types that were registered using 'publicly_queryable' set to true.

Last edited 3 years ago by fireproofsocks (previous) (diff)

comment:10 @jeremyfelt3 years ago

I did some digging a bit ago in the search for what the ever vague 'public' meant. It is definitely a thing of it's own and it happens to flag a few other things in the process if they are not explicitly set.

A full writeup on the digging is here, including where exactly in core 'public', 'publicly_queryable', 'show_ui' and the rest are used: http://jeremyfelt.com/wordpress/2012/05/07/exploring-intention-when-registering-custom-post-types-in-wordpress/

In a nutshell - 'public' is the correct attribute to use when querying for post types that are intended to be public. 'publicly_queryable' is used very specifically and there is some (IMO rightful) interest in eliminating it entirely during the 3.5 cycle.

For reference, the ticket that got me caught up in the definition was 19693, though there are plenty out there. One of the things that resulted from that was the patch for register_post_type() documentation in 3.4, 20734, which provides much more detail for each of the arguments.

comment:11 @fireproofsocks3 years ago

Thanks, Jeremy, that's the kind of thoughtful attention this issue and its referenced functions need. Yes, I would agree 100% that either one or the other attribute has to go. We only need one: public or publicly_queryable, not both -- removing one would fix this issue entirely. I would also love to change the inverted nature of the "exclude_from_search" option while I'm at it.

comment:12 @markoheijnen3 years ago

I didn't confuse the two arguments. The ticket for show_ui was just an example.

I believe public or publicly_queryable can't be removed. I would say that the public argument should be a convenient argument. Reading through #19693 that is not the case. I'm curious how the going to change the functionality.

I do however still believe that the actual result is the correct behavior

comment:13 @c3mdigital2 years ago

  • Keywords close 2nd-opinion removed
  • Resolution set to invalid
  • Status changed from new to closed

Closing as invalid based on comments above and in ticket #19693. Please reopen if you anything additional to add.

comment:14 @SergeyBiryukov2 years ago

  • Milestone Awaiting Review deleted
  • Severity changed from major to normal
Note: See TracTickets for help on using tickets.