get_post( int|WP_Post|null $post = null, string $output = OBJECT, string $filter = 'raw' ): WP_Post|array|null
- Since
- 1.5.1
- Source
wp-includes/post.php:1092
Fetches a single post as a WP_Post object, associative array, or numeric array from an ID, a post object, or the current global post. Falls back to the global $post inside the loop when the $post argument is empty, and returns null if a numeric ID does not match an existing post. Use sanitize_post() to see exactly what each $filter value ('raw', 'edit', 'db', 'display') does to the returned fields.
Description
See sanitize_post() for optional $filter values. Also, the parameter $post, must be given as a variable, since it is passed by reference.
Compatibility
- WordPress
- since 1.5.1
- 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
$postint|WP_Post|nulloptional- Post ID or post object.
null,false,0and other PHP falsey values return the current global post inside the loop. A numerically valid post ID that points to a non-existent post returnsnull. Defaults to global $post.Default:null $outputstringoptional- The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to a WP_Post object, an associative array, or a numeric array, respectively. Default OBJECT.Default:
OBJECT $filterstringoptional- Type of filter to apply. Accepts 'raw', 'edit', 'db', or 'display'. Default 'raw'.Default:
'raw'
Return value
WP_Post|array|null- Type corresponding to $output on success or null on failure.
When $output is OBJECT, aWP_Postinstance is returned.
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.
Get a post by ID as an associative array
Fetch post ID 2 from the baseline fixtures and dump it as an array instead of a WP_Post object.
$post_array = get_post( 2, ARRAY_A );
if ( null === $post_array ) {
echo esc_html( 'No post found with that ID.' );
} else {
echo '<pre>' . esc_html( print_r( $post_array, true ) ) . '</pre>';
}ARRAY_A returns the same fields WP_Post would expose as an object, just as a plain array with no meta included.
Get the current post inside a custom loop without passing an ID
Run a small WP_Query over the five baseline posts and call get_post() with no argument to pull whatever the_post() just set as the global post.
$query = new WP_Query( array(
'post_type' => 'post',
'posts_per_page' => 5,
) );
while ( $query->have_posts() ) {
$query->the_post();
$current = get_post();
echo esc_html( $current->post_title ) . '<br>';
}
wp_reset_postdata();Calling get_post() with no argument only works reliably while a loop has set up the global $post via the_post(); outside a loop it will pick up whatever $post happens to be set globally, if anything.
Common problems and fixes · 4
- Why does get_post() give me the wrong post when I call it without an ID?
- Why does get_post() return null even though the ID looks correct?
- Why do post titles or content look different depending on which function I use?
- Why didn't changing a property on the object returned by get_post() update the post?
Why does get_post() give me the wrong post when I call it without an ID?
Why does get_post() return null even though the ID looks correct?
Why do post titles or content look different depending on which function I use?
Why didn't changing a property on the object returned by get_post() update the post?
Alternatives and related functions
get_posts- When you need a filtered list of multiple posts (by category, tag, meta, etc.) rather than a single known post.
WP_Query- When you need full control over post retrieval, pagination, or complex query arguments beyond a single ID lookup.
get_post_field- When you only need one field from a post (like post_title) and want a lighter call than building a full WP_Post object.
get_the_title- When you're already inside The Loop or have a post ID and just want an escaped, filtered title string for display.
Performance profile
How much work a call to get_post() 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
- Heavy
- Scaling
- Constant
- Instructions
- 11–42
- Plugin surface
- None
- Called by
- 50
Reaches the database via get_post().
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 68.
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 it touches
- querycontent query
get_post()this function does it
Further down the call graph this can also reach hook, option, cache, serialize and transient. Those are the worst case, several calls deep and usually down an error path, not what a normal call pays.
What one call costs · 12 distinct outcomes
One number would be a lie: the work depends on which branch runs. These are every distinct cost get_post() can have, taken from its control-flow graph on PHP 8.5.
| When | Instructions | Calls it makes |
|---|---|---|
| always | 11–25 | none |
!($post instanceof) | 15–27 | ::WP_Post() |
$output === false | 20–34 | ->filter(), ->to_array() |
$output !== false | 21–35 | ->filter() |
!($post instanceof) && is_object($post) && empty($post) | 23–27 | sanitize_post() |
!($post instanceof) && $output === false | 24–36 | ::WP_Post(), ->filter(), ->to_array() |
!($post instanceof) && $output !== false | 25–37 | ::WP_Post(), ->filter() |
| always | 26–40 | ->filter(), ->to_array(), array_values() |
!($post instanceof) | 30–42 | ::WP_Post(), ->filter(), ->to_array(), array_values() |
!($post instanceof) && is_object($post) && empty($post) && $output === false | 32–36 | sanitize_post(), ->filter(), ->to_array() |
!($post instanceof) && is_object($post) && empty($post) && $output !== false | 33–37 | sanitize_post(), ->filter() |
!($post instanceof) && is_object($post) && empty($post) | 38–42 | sanitize_post(), ->filter(), ->to_array(), array_values() |
Across PHP versions
| PHP | Compiled | Executed | Branches | Notes |
|---|---|---|---|---|
| 8.6-dev | 68 | 11–42 | 9 | |
| 8.5 | 68 | 11–42 | 9 | |
| 8.4 | 68 | 11–42 | 9 | |
| 8.3 | 68 | 11–42 | 9 | |
| 8.2 | 68 | 11–42 | 9 | |
| 8.1 | 68 | 11–42 | 9 | 2 fewer instructions than PHP 7.4 |
| 7.4 | 70 | 11–44 | 9 |
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.
Uses · 3
- sanitize_post()Sanitizes every post field.
- WP_Post::__construct()Constructor.
- WP_Post::get_instance()Retrieve WP_Post instance.
Used by · 50
- Custom_Image_Header::create_attachment_object()Creates an attachment 'object'.
- File_Upload_Upgrader::__construct()Construct the upgrader for a form.
- TwentyTwenty_Walker_Page::start_el()Outputs the beginning of the current element in the tree.
- WP_Comment::__get()Magic getter.
- WP_Comment::__isset()Determines whether a non-public property is set.
- WP_Comments_List_Table::column_response()
- WP_Comments_List_Table::single_row()
- WP_Customize_Control::render_content()Render the control's content.
- WP_Customize_Manager::_publish_changeset_values()Publishes the values of a changeset.
- WP_Customize_Manager::customize_pane_settings()Prints JavaScript settings for parent window.
- WP_Customize_Manager::get_changeset_post_data()Gets the data stored in a changeset post.
- WP_Customize_Manager::import_theme_starter_content()Imports theme starter content into the customized state.
Show all 50
- WP_Customize_Manager::save()Handles customize_save WP Ajax request to save/update a changeset.
- WP_Customize_Manager::save_changeset_post()Saves the post for the loaded changeset.
- WP_Customize_Manager::trash_changeset_post()Trashes or deletes a changeset post.
- WP_Customize_Nav_Menu_Item_Setting::get_original_title()Get original title.
- WP_Customize_Nav_Menu_Item_Setting::value()Get the instance data for a given nav_menu_item setting.
- WP_Customize_Nav_Menus::insert_auto_draft_post()Adds a new `auto-draft` post.
- WP_Customize_Nav_Menus::load_available_items_query()Performs the post_type and taxonomy queries for loading available 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_Embed::cache_oembed()Triggers a caching of all oEmbed results.
- WP_Embed::maybe_run_ajax_cache()If a post/page was saved, then output JavaScript to make an Ajax request that will call WP_Embed::cache_oembed().
- WP_Embed::shortcode()The do_shortcode() callback function.
- WP_List_Table::comments_bubble()Displays a comment count bubble.
- WP_Media_List_Table::column_parent()Handles the parent column output.
- WP_Navigation_Block_Renderer::get_inner_blocks_from_navigation_post()Gets the inner blocks for the navigation block from the navigation post.
- WP_Navigation_Block_Renderer::get_navigation_name()Gets the name of the current navigation, if it has one.
- WP_Posts_List_Table::_page_rows()Displays the nested hierarchy of sub-pages together with paging support, based on a top level page ID.
- WP_Posts_List_Table::column_title()Handles the title column output.
- WP_Posts_List_Table::single_row()
- WP_Privacy_Policy_Content::notice()Adds a notice with a link to the guide when editing the privacy policy page.
- WP_Query::generate_postdata()Generates post data.
- 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::setup_postdata()Sets up global post data.
- WP_REST_Attachments_Controller::create_item()Creates a single attachment.
- WP_REST_Attachments_Controller::edit_media_item()Applies edits to a media item and creates a new attachment record.
- WP_REST_Attachments_Controller::insert_attachment()Inserts the attachment post in the database. Does not update the attachment meta.
- WP_REST_Attachments_Controller::post_process_item()Performs post-processing on an attachment.
- WP_REST_Attachments_Controller::update_item()Updates a single attachment.
- WP_REST_Autosaves_Controller::create_item()Creates, updates or deletes an autosave revision.
- WP_REST_Autosaves_Controller::create_post_autosave()Creates autosave for the specified post.
- WP_REST_Block_Renderer_Controller::get_item()Returns block output from block's registered render_callback.
- WP_REST_Block_Renderer_Controller::get_item_permissions_check()Checks if a given request has access to read blocks.
- WP_REST_Comments_Controller::check_read_permission()Checks if the comment can be read.
- WP_REST_Comments_Controller::create_item_permissions_check()Checks if a given request has access to create a comment.
- WP_REST_Comments_Controller::get_comment()Get the comment, if the ID is valid.
- WP_REST_Comments_Controller::get_item_permissions_check()Checks if a given request has access to read the comment.
- WP_REST_Comments_Controller::get_items_permissions_check()Checks if a given request has access to read comments.
- WP_REST_Comments_Controller::prepare_links()Prepares links for the request.
Source code
function get_post( $post = null, $output = OBJECT, $filter = 'raw' ) { if ( empty( $post ) && isset( $GLOBALS['post'] ) ) { $post = $GLOBALS['post']; } if ( $post instanceof WP_Post ) { $_post = $post; } elseif ( is_object( $post ) ) { if ( empty( $post->filter ) ) { $_post = sanitize_post( $post, 'raw' ); $_post = new WP_Post( $_post ); } elseif ( 'raw' === $post->filter ) { $_post = new WP_Post( $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 ( ARRAY_A === $output ) { return $_post->to_array(); } elseif ( ARRAY_N === $output ) { return array_values( $_post->to_array() ); } return $_post;}Changelog
Introduced in 1.5.1. One change between 6.7.7 and 7.1.0.
Signature, return type and hooks compared across 5 parsed releases.
$post retyped from int|WP_Post|null to int|object|null.verified against sourceAbout this page
- Parsed data
- Generated from the wordpress-develop 6.7.7 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.