get_post_type_object( string $post_type ): WP_Post_Type|null
- Since
- 3.0.0, 4.6.0
- Source
wp-includes/post.php:1656
Look up the WP_Post_Type object registered for a given post type name, returning null if that type isn't registered. It reads directly from the global $wp_post_types array populated by register_post_type(), so it only sees types already registered on the current request. Pair it with post_type_exists() when you only need a true/false check rather than the full object.
Compatibility
- WordPress
- since 4.6.0
- PHP
- 7.4–8.6-dev
- 6.7.7
- 6.8.8
- 6.9.7
- 7.0.4
- 7.1.0
Present in every tracked release (6.7.7 to 7.1.0), and compiles on PHP 7.4 through 8.6-dev.
Parameters
$post_typestring- The name of a registered post type.
Return value
WP_Post_Type|null- WP_Post_Type object if it exists, null otherwise.
Code examples
Every example is editable and runs in a real WordPress booted in your browser by WordPress Playground. Press Run, then edit the code: clicking away re-runs it. Nothing is sent anywhere until you do.
Check whether a post type is hierarchical before building a menu
Inspect the built-in 'page' post type's properties to decide how to render an admin listing.
$post_type_object = get_post_type_object( 'page' );
if ( $post_type_object ) {
printf(
'The "page" post type is %s and %s show up in the admin menu.',
esc_html( $post_type_object->hierarchical ? 'hierarchical' : 'non-hierarchical' ),
esc_html( $post_type_object->show_in_menu ? 'will' : 'will not' )
);
} else {
echo 'No such post type is registered.';
}Read the admin labels of a custom post type
Register a 'book' post type and pull its label object to reuse the singular and plural names elsewhere.
$book_type = get_post_type_object( 'book' );
if ( $book_type ) {
echo esc_html( sprintf( 'Singular label: %s | Plural label: %s', $book_type->labels->singular_name, $book_type->labels->name ) );
} else {
echo 'The book post type is not registered.';
}Common problems and fixes · 4
- Why does get_post_type_object() return null for my custom post type?
- Can I pass an array of post type names to get_post_type_object()?
- How do I get the object for every registered post type, not just one?
- If I change a property on the object I get back, does it affect the rest of the request?
Why does get_post_type_object() return null for my custom post type?
Can I pass an array of post type names to get_post_type_object()?
is_scalar( $post_type ) first and returns null immediately for anything that isn't a scalar, so an array short-circuits the lookup.How do I get the object for every registered post type, not just one?
If I change a property on the object I get back, does it affect the rest of the request?
Alternatives and related functions
post_type_exists- When you only need a true or false answer about whether a post type is registered, not the object itself.
get_post_types- When you need the names or objects for every registered post type instead of one specific type.
get_post_type- When you have a post ID or WP_Post object and just want the post type slug it belongs to.
register_post_type- When the post type doesn't exist yet and you need to define it before you can look it up.
Performance profile
How much work a call to get_post_type_object() does, and what it touches: the algorithmic scaling, the Zend instruction count per call across PHP versions, the hooks it hands control to, and the core code that calls it. Measured from the compiled opcodes, not a stopwatch, so every number is identical on any machine running the same PHP version, and every function in core is ranked by cost.
- Cost class
- Trivial
- Scaling
- Constant
- Instructions
- 5–8
- Plugin surface
- None
- Called by
- 50
Touches nothing outside its own arguments.
No loop in the body: the same number of instructions runs whatever you pass in.
Executed per call on PHP 8.5, depending on the branch taken. The body compiles to 9.
Nothing here hands control to plugin code.
50 places in core call this, so the cost is paid more often than your own code shows.
What one call costs · 1 distinct outcome
One number would be a lie: the work depends on which branch runs. These are every distinct cost get_post_type_object() can have, taken from its control-flow graph on PHP 8.5.
| When | Instructions | Calls it makes |
|---|---|---|
| always | 5–8 | none |
Across PHP versions
| PHP | Compiled | Executed | Branches | Notes |
|---|---|---|---|---|
| 8.6-dev | 9 | 5–8 | 2 | |
| 8.5 | 9 | 5–8 | 2 | |
| 8.4 | 9 | 5–8 | 2 | |
| 8.3 | 9 | 5–8 | 2 | |
| 8.2 | 9 | 5–8 | 2 | |
| 8.1 | 9 | 5–8 | 2 | 2 fewer instructions than PHP 7.4 |
| 7.4 | 11 | 7–10 | 2 |
An instruction is not a fixed amount of time, so a matching count is not necessarily the same speed; what it rules out is a difference in the work itself.
Used by · 50
- WP_Comments_List_Table::column_response()Outputs the response column.
- WP_Customize_Control::render_content()Renders the control's content.
- WP_Customize_Manager::check_changeset_lock_with_heartbeat()Checks locked changeset with heartbeat API.
- WP_Customize_Manager::customize_pane_settings()Prints JavaScript settings for parent window.
- WP_Customize_Manager::grant_edit_post_capability_for_changeset()Re-maps 'edit_post' meta cap for a customize_changeset post to be the same as 'customize' maps.
- WP_Customize_Manager::handle_changeset_trash_request()Handles request to trash a changeset.
- WP_Customize_Manager::handle_dismiss_autosave_or_lock_request()Deletes a given auto-draft changeset or the autosave revision for a given changeset or delete changeset lock.
- WP_Customize_Manager::handle_override_changeset_lock_request()Removes changeset lock when take over request is sent via Ajax.
- WP_Customize_Manager::save()Handles customize_save WP Ajax request to save/update a changeset.
- WP_Customize_Nav_Menu_Item_Setting::get_original_title()Get original title.
- WP_Customize_Nav_Menu_Item_Setting::get_type_label()Get type label.
- WP_Customize_Nav_Menus::ajax_insert_auto_draft_post()Ajax handler for adding a new auto-draft post.
Show all 50
- WP_Customize_Nav_Menus::enqueue_scripts()Enqueues scripts and styles for Customizer pane.
- WP_Customize_Nav_Menus::load_available_items_query()Performs the post_type and taxonomy queries for loading available menu items.
- WP_Customize_Nav_Menus::print_post_type_container()Prints the markup for new menu items.
- WP_Customize_Nav_Menus::sanitize_nav_menus_created_posts()Sanitizes post IDs for posts created for nav menu items to be published.
- WP_List_Table::months_dropdown()Displays a dropdown for filtering items in the list table by month.
- WP_Media_List_Table::column_parent()Handles the parent column output.
- WP_Posts_List_Table::__construct()Constructor.
- WP_Posts_List_Table::ajax_user_can()
- WP_Posts_List_Table::column_title()Handles the title column output.
- WP_Posts_List_Table::extra_tablenav()
- WP_Posts_List_Table::get_bulk_actions()
- WP_Posts_List_Table::handle_row_actions()Generates and displays row action links.
- WP_Posts_List_Table::inline_edit()Outputs the hidden row displayed when inline editing
- WP_Posts_List_Table::no_items()
- WP_Query::get_posts()Retrieves an array of posts based on query variables.
- WP_Query::get_queried_object()Retrieves the currently queried object.
- WP_Query::is_post_type_archive()Determines whether the query is for an existing post type archive page.
- WP_Query::parse_query()Parses a query string and sets query type booleans.
- WP_REST_Autosaves_Controller::__construct()Constructor.
- WP_REST_Comments_Controller::check_read_post_permission()Checks if the post can be read.
- WP_REST_Font_Faces_Controller::get_items_permissions_check()Checks if a given request has access to font faces.
- WP_REST_Font_Families_Controller::get_items_permissions_check()Checks if a given request has access to font families.
- WP_REST_Global_Styles_Controller::get_available_actions()Get the link relations available for the post and current user.
- WP_REST_Global_Styles_Revisions_Controller::__construct()Constructor.
- WP_REST_Menu_Items_Controller::prepare_item_for_database()Prepares a single nav menu item for create or update.
- WP_REST_Navigation_Fallback_Controller::get_item_permissions_check()Checks if a given request has access to read fallbacks.
- WP_REST_Post_Types_Controller::get_item()Retrieves a specific post type.
- WP_REST_Posts_Controller::__construct()Constructor.
- WP_REST_Posts_Controller::check_create_permission()Checks if a post can be created.
- WP_REST_Posts_Controller::check_delete_permission()Checks if a post can be deleted.
- WP_REST_Posts_Controller::check_is_post_type_allowed()Checks if a given post type can be viewed or managed.
- WP_REST_Posts_Controller::check_read_permission()Checks if a post can be read.
- WP_REST_Posts_Controller::check_update_permission()Checks if a post can be edited.
- WP_REST_Posts_Controller::create_item_permissions_check()Checks if a given request has access to create a post.
- WP_REST_Posts_Controller::get_available_actions()Gets the link relations available for the post and current user.
- WP_REST_Posts_Controller::get_collection_params()Retrieves the query params for the posts collection.
- WP_REST_Posts_Controller::get_item()Retrieves a single post.
- WP_REST_Posts_Controller::get_item_schema()Retrieves the post's schema, conforming to JSON Schema.
Source code
function get_post_type_object( $post_type ) { global $wp_post_types; if ( ! is_scalar( $post_type ) || empty( $wp_post_types[ $post_type ] ) ) { return null; } return $wp_post_types[ $post_type ];}Changelog
Introduced in 3.0.0. Unchanged from 6.7.7 through 7.1.0.
Signature, return type and hooks compared across 5 parsed releases.
WP_Post_Type.from the docblockAbout this page
- Parsed data
- Generated from the wordpress-develop 7.1.0 tag, from
src/wp-includes/post.php, and regenerated for each WordPress release so it tracks the code rather than a snapshot of it. - Corrections
- Something wrong on this page? Report it and it gets fixed in the next regeneration.