Posts in WordPress
In this article, let's talk about WordPress posts, or rather how their structure is arranged in the WordPress engine. There is a lot of information on the Internet about what posts in WordPress are and how they differ from static pages. Many of them is good, but designed for beginners, and if we dig deeper, there's more to talk about on this topic.
See also:
- Taxonomies in WordPress
- Metadata in WordPress
- register_post_type()
- get_post_type_object() - gets the post type object data.
The first thing to do is to separate the concept of "Posts" into a narrow and a broad one.
Post in a Narrow sense
Is the basic WordPress posts - the post
post type.
This is publishing an post with the post
post type, which exists in WordPress immediately after installation. Such post can be attached to categories or tags. Such "posts" can be contrasted with "pages" (publishing an entry with the page
post type).
Post in a Broad sense
It is a post of any post type: post
, page
, custom post type
.
It is any element that contain site data (content). All such data is written to the database, in the wp_posts
table.
Since all the elements are in the same table - they have the same data, and therefore technically they are not very different from each other. I would distinguish 3 main differences:
-
Tree structure. One post can be a child or a parent to another. This is the structure of static pages.
-
Name of post type. Each post type has its own name: posts are called
post
, pagespage
, user-created types are called as they are named, for exampleportfolio
.I highlighted this distinction because the
post_type
field in thewp_posts
table is indexed. So figuratively we can say that the type divides the table into separate smaller tables based on the type of post, i.e. during a query to select posts, WordPress very quickly "cuts down" the table to the specified post type and works only with that type. - Built-in post types. This includes all non-standard post types:
revisions
,menu items
(nav menu),attachments
(media files). That is, these are posts that are used and processed in WordPress in a special way.
Default post Types (post_type)
The following post types are registered in WordPress by default.
Type name | Title | Description |
---|---|---|
post |
Posts | Regular WP posts. |
page |
Pages | Static WP Pages. |
custom_name |
Custom post type | Entries created with register_post_type(). |
attachment |
Attachments | WP media files: images, audio, video. |
nav_menu_item |
Menu items | WP's built-in type, for menus. |
revision |
Revisions | Built-in WP type, for post editing copies. |
oembed_cache |
oEmbed Responses | Responses for oEmbed requests. |
custom_css |
Custom CSS | CSS styles specified in the customizer. See wp_get_custom_css_post() |
customize_changeset |
Changesets | Customizer settings. |
user_request |
User Requests | Requests when changing personal data on the admin tools page. See. wp_create_user_request() |
wp_block |
Reusable Blocks | Gutenberg Blocks. |
wp_template |
Templates | Templates to include in your theme. (block editor) |
wp_template_part |
Template Parts | Template parts to include in your templates. (block editor) |
wp_global_styles |
Global Styles | Global styles to include in themes. (block editor) |
wp_navigation |
Navigation Menus | Navigation menus that can be inserted into your site. (block editor) |
Default post types are registered by the function create_initial_post_types().
Default Posts Statuses (post_status)
The following post statuses are used in WordPress out of the box.
Status | Description |
---|---|
publish |
Published post (page, post, custom post type). |
pending |
Post under review before publication.. |
draft |
Post draft. |
auto-draft |
Just created a post, not yet a title, content or other information. |
future |
An post scheduled for publication in the future. |
private |
A post is not available to unauthorized users. |
inherit |
revision or attachment. See get_children(). |
trash |
Post that are in the trash bin. |
Posts status related functions (full list see here):
Function | Description |
---|---|
get_post_status_object() | Retrieve a post status object by name. |
is_post_status_viewable() | Determines whether a post status is considered "viewable". |
get_post_statuses() | Retrieve all of the WordPress supported post statuses. |
Each field of the wp_posts
table:
Field | Value | Index |
---|---|---|
ID | Post ID. | primary_key |
post_author | Post author ID. | post_author |
post_date | Date of post (in site range). | type_status_date |
post_date_gmt | Date of post (GMT/UTC range). | - |
post_content | Content of the post (post or page text). | - |
post_title | Post title. | - |
post_excerpt | A short text of the post (excerpt, extract, quote). | - |
post_status | Post status (publish, inherit, trash). | type_status_date |
comment_status | Whether comments are allowed (open, closed). | - |
ping_status | Whether pings are allowed (open, closed). | - |
post_password | Password for access to the post. | - |
post_name | The post's slug. The name used in URLs. | post_name |
to_ping | URLs to which a ping should be sent when publishing. | - |
pinged | URL to which a ping was sent. | - |
post_modified | The date the post was changed (in site range). | - |
post_modified_gmt | The date the post was changed (in GMT/UTC range). | - |
post_content_filtered | The temporary content of the post. Read more | - |
post_parent | The parent post ID. | post_parent |
guid | The unique identifier of the post. For feeds. | - |
menu_order | Numerical order in the menu. | - |
post_type | Post type: post , page . |
type_status_date |
post_mime_type | MIME type of the post. For attachments: image/jpeg , video/mp4 . |
- |
comment_count | The number of comments on the post. | - |
As you can see, there are common fields for all posts types, e.g: post_type
, post_title
. And there are special fields which used only for specific post types. For example, the field post_mime_type
is used only for attachments, the field post_parent
is used for hierarchical (tree-type) posts, the fields to_ping
and pinged
are used for posts with content, for example: posts, pages, custom post types.
Indexed fields play a big role in this table: post_name
, post_parent
, post_author
, post_type + post_status + post_date
(composite index). Indexes are needed to speed up queries on selecting posts. I won't go into details of indexes. You can read about them in the excellent article Indexes in MySQL.
At this point, I think we can finish with the concept of "posts in WordPress" and move on to other important knowledge.
Difference between post_content_filtered
and post_content
post_content_filtered
- place where temporary content is stored. WordPress doesn't use this field at all, it's for plugins. It's set as empty every time you update a post, except when it's specified. That is, if this field is specified when the post is updated, it will be written, but if it is not specified on another update, it will be erased.
Detailed answer on this topic here: http://wordpress.stackexchange.com/questions/113387/when-is-the-post-content-filtered-column-in-database-cleared-by-wordpress
Metadata — Additional Post Data
Tasks during development can be very different and the available fields in the wp_posts
table is always not enough. Therefore, to expand capabilities, any post in WordPress, ie, any string in the `wp_posts
table can have additional data. Such data are called: metadata, they are also called meta-fields, custom fields.
Any of metadata are stored in the wp_postmeta
DB table:
wp_postmeta Table
Field | Value | Index |
---|---|---|
meta_id | Meta-data ID. Internal field used by WP core. | PRIMARY |
post_id | Post ID from wp_posts table. | post_id |
meta_key | The key (name) of the metadata. | meta_key |
meta_value | The value of the metadata. Always a string, arrays are stored in serialized form. | - |
For post, page meta-fields can be controlled on the post edit page:
Notes about meta-fields (metadata, custom fields)
-
Revisions have no metadata.
-
Meta-field whose name starts with underscore (
_
) is perceived by WP as hidden and is not displayed in admin by default.So for example in the WP there are the following hidden meta-fields for posts:
_wp_page_template
- saved name of the php file template, if the page was specified as a template file._edit_lock
- records the timestamp and ID of the user who edits the post._edit_last
- ID of the user who last edited the post._thumbnail_id
- ID of the post thumbnail (attachment).
-
To manage metadata I have a small class Kama_Post_Meta_Box. There are also more powerful plugins:
- More about WordPress metadata
Post meta functions
To manage metadata in the code of a theme or plugin, there are special functions:
get_post_meta() | Gets the value of the specified custom field of the post. Also can get an array of all post meta fields. |
add_post_meta() | Adds meta field to the specified post. |
update_post_meta() | Updates specified meta field of specified post. Or adds it, if it's not exists. |
delete_post_meta() | Remove metadata matching criteria from a post. |
get_post_custom() | Retrieve post meta fields, based on post ID. |
get_post_custom_keys() | Retrieve meta field names for a post. |
get_post_custom_values() | Retrieve values for a custom post field. |
the_meta() | Display list of post custom fields. |
Posts relations with parent posts and taxonomies
Since any content needs to be structured for easy reading, posts can be linked together:
-
Hierarchical posts are linked to each other as parent and child. And they are normally not linked to headings (taxonomies). The tree-like link is written in the
post_parent
field of thewp_posts
table. - Non-tree-like (linear) entries are linked via headings, labels and arbitrary taxonomies. Their
post_parent
field is always 0 and is not used.
Detailed explanation of what taxonomies in WordPress are.
Schematically it looks like this:
Relation in non-standard posts types:
- Menu items - use the logic of tree entries to link between them.
- Revisions and attachments - are attached to the parent post through the
post_parent
field of thewp_posts
table.
Notes
Post content Cleaning / Sanitizing
Post content and post excerpt are cleaned/sanitized with wp_filter_post_kses() before saving it to the database. The function is hung on (field_no_prefix)_save_pre hook:
add_filter( 'content_save_pre', 'wp_filter_post_kses' ); add_filter( 'excerpt_save_pre', 'wp_filter_post_kses' );
These hooks are triggered from: