Make WordPress Core

Opened 5 years ago

Closed 4 years ago

Last modified 4 years ago

#12966 closed defect (bug) (fixed)

get_post_types returning more than desired results

Reported by: michaelh Owned by:
Milestone: 3.0 Priority: normal
Severity: normal Version: 3.0
Component: Posts, Post Types Keywords: has-patch tested
Focuses: Cc:


In addition to the desired custom post types, other extraneous post types such as posts, pages, and attachments, are being returned with this get_post_types example:

//get list of public queryable, custom post types
  'publicly_queryable' => true,
  '_builtin' => false
$output = 'objects'; // names or objects
  foreach ($post_types  as $post_type ) {
    echo "<pre>"; print_r($post_type); echo "</pre>";

Using this fares no better:

  'public' => true,
  '_builtin' => false

Attachments (3)

12966.diff (666 bytes) - added by sivel 5 years ago.
Fixes the function to follow the way it is documented
12966.2.diff (3.5 KB) - added by scribu 5 years ago.
introduce wp_filter_object_list()
12966.3.diff (7.8 KB) - added by scribu 5 years ago.
add $operator argument

Download all attachments as: .zip

Change History (27)

comment:1 @scribu5 years ago

  • Keywords reporter-feedback added
  • Milestone set to 3.0

Please provide the output of this code:

global $wp_post_types;


  'public' => true,
  '_builtin' => false
$post_types = get_post_types($args, $output);


comment:2 @nacin5 years ago

Not near my dev machine to test, but I also saw something like this. I think I was using public and show_ui at the same time, and I was getting incorrect results.

comment:4 @scribu5 years ago

Sorry, I forgot to mention that you should use "View Page Source" so that spaces are preserved.

comment:7 @michaelh5 years ago

Here's the custom post types from my functions.php

register_post_type('property', array(
	'label' => __('Real Estate'),
	'singular_label' => __('Property'),
	'public' => true,
	'show_ui' => true, // UI in admin panel
	'capability_type' => 'post',
	'hierarchical' => false,
	'rewrite' => array("slug" => "property"), // Permalinks format
	'supports' => array('title','author')

register_post_type('podcast', array(
	'label' => __('Podcasts'),
	'singular_label' => __('Podcast'),
	'public' => true,
	'show_ui' => true,
	'capability_type' => 'post',
	'hierarchical' => false,
	'rewrite' => false,
	'query_var' => false,
	'supports' => array('title', 'editor', 'author')

register_post_type('classified', array(
	'label' => 'Classifieds',
	'singular_label' => 'Classified',
	'_builtin' => false,
	'public' => true,
	'publicly_queryable' => true,
	'show_ui' => true, // UI in admin panel
	'capability_type' => 'post'

comment:8 @sivel5 years ago

The problem is with the way the function is documented and how it works. The docs say "Only post types having attributes that match all arguments are returned". However it really returns all post types that match at least 1 of the args. I have a patch coming that fixes this function to perform the way I think it should as well as match the documentation.

@sivel5 years ago

Fixes the function to follow the way it is documented

comment:9 @sivel5 years ago

  • Cc matt@… added
  • Keywords has-patch added; reporter-feedback removed

This patch counts the number of intersections found and compares it to the number of arguments that were passed instead of just checking that intersections were found.

comment:10 @nacin5 years ago

This probably also effects get_taxonomies().

@scribu5 years ago

introduce wp_filter_object_list()

comment:11 follow-up: @scribu5 years ago

Thanks, michaelh.

Heh, I only saw sivel's patch now.

I took it a step further and created a more general function that's used by both get_post_types() and get_taxonomies().

comment:12 in reply to: ↑ 11 @sivel5 years ago

I took it a step further and created a more general function that's used by both get_post_types() and get_taxonomies().

At least we took the same approach to fixing it. Good catch on taxonomies, I had only been working on post types and it didn't occur to me to test taxonomies.

comment:13 @nacin5 years ago

Looks like get_post_stati() already performs the count correctly. I would suggest moving it over to the helper, but it actually allows for an OR operator, which is something we could potentially introduce to these as well.

Standardization of arguments and functionality is a developer's best friend when they actually have to leverage the API.

comment:14 @rovo895 years ago

An alternative to

if ( count(array_intersect_assoc(get_object_vars($obj), $args)) == $count )

would be

if ( empty(array_diff_assoc($args, get_object_vars($obj))) )

which should provide the same functionality, but might be slightly faster.

comment:15 @nacin5 years ago

Can't call empty() like that, needs to be a variable. Good thought though and there's a few ways to take that and make it work. But we're dealing with negligible performance at that point.

comment:16 @michaelh5 years ago

Thanks both scribu and sivel.

Applied 12966.2.diff and using

$output = 'objects'; // names or objects

get this error:

Warning: array_intersect_assoc() [function.array-intersect-assoc]: Argument #2 is not an array in C:\xampp\htdocs\wp30\wp-includes\functions.php  on line 2929

@scribu5 years ago

add $operator argument

comment:17 @scribu5 years ago

So, 12966.3.diff:

  • adds an empty($args) check to prevent the warning mentioned by michaelh above.
  • adds the $operator argument to wp_filter_object_list(), get_post_types() and get_taxonomies()
  • refactors get_post_stati() to use wp_filter_object_list()

Seeing that get_post_stati() was only introduced in 3.0, I took the liberty of switching the default value for the $operator argument from 'or' to 'and'. This makes it consistent with get_post_types() and get_taxonomies() and it's also the more common use-case.

I've double-checked that this change doesn't affect it's usage in core.

comment:18 @michaelh5 years ago

12966.3 works good with a variety of arguments, including $operator, using get_post_types()

comment:19 @scribu5 years ago

  • Keywords tested added

I'm pretty happy with it.

comment:20 @michaelh5 years ago

  • Component changed from Template to Post Types

comment:21 @nacin5 years ago

  • Resolution set to fixed
  • Status changed from new to closed


Introduce the wp_filter_object_list() helper, with an $operator arg. Fixes an intersection bug in get_post_types() and get_taxonomies(). Also switches $operator default from 'or' to 'and' for get_post_stati(). props scribu, fixes #12966.

comment:22 @Ov3rfly4 years ago

  • Keywords 2nd-opinion added
  • Resolution fixed deleted
  • Status changed from closed to reopened
  • Version changed from 3.0 to 3.2.1

Seems still not to work as expected, example:

		$args = array(
			'public'   => true,
			'_builtin' => false,
			'taxonomies' => array('post_tag')
		$post_types = get_post_types($args, 'objects'); 

Expected results: All public custom post types with (at least) taxonomy 'post_tag'.

Actual results: All public custom post types, also if they do not have 'post_tag' set as taxonomy.

Result of above print_r() http://pastebin.com/4dL7i0DU

Note the empty taxonomies at post type slider:

    [slider] => stdClass Object
            [taxonomies] => Array

http://codex.wordpress.org/Function_Reference/get_post_types lists 'taxonomies' as valid argument.

Related older thread, but no discussion there: http://wordpress.org/support/topic/get_post_types-returns-more-than-expected

comment:23 @ocean904 years ago

  • Keywords 2nd-opinion removed
  • Resolution set to fixed
  • Status changed from reopened to closed
  • Version changed from 3.2.1 to 3.0

This ticket was closed on a completed milestone. New ticket, please.

Note: See TracTickets for help on using tickets.