Chapter 2. WordPress Basics

WordPress was first developed in 2003 and was created primarily as blogging software. By the release of version 3.5, the image of WordPress had changed from blogging software to a versatile CMS and the word “blog” was actually removed from the description of the software and most places in the source code. Today, WordPress has evolved to become the largest platform on the web and is used on about 30% of all websites on the internet. This is pretty amazing if you think about it. More than a half a billion internet websites run on top of WordPress.

WordPress has gained so much popularity over the years for a couple of reasons. The first is that WordPress is open source software and has an entire community of people invested in improving it and continually contributing new code to extend its functionality. WordPress users, developers, and designers are always thinking of new creative ways to use WordPress and creating plugins for these new features, which can be made available to the community.

Another reason that WordPress has been so successful is the fact that it’s an extremely flexible CMS laced with hooks and filters so plugin and theme developers can have almost total control to build all different kinds of websites. Developers are constantly exploring innovative new ways to use the software, including building web and mobile applications, which is the focus of this book. The use of hooks and filters is covered later in this chapter.

Note

We are going to assume that you already know how to use WordPress and have already installed the latest version. If this is your first time using WordPress, check out the WordPress home page to familiarize yourself with it.

WordPress Directory Structure

Let’s take a quick top-level look at the folders and files that are included within a typical WordPress install.

Root Directory

In the root directory, there are a few core WordPress files. Unless you are digging around in the core WordPress code looking for hooks to use or trying to learn how certain functionality is coded, the only core WordPress file you may need to ever access is wp-config.php. You should never, ever, ever, ever1 alter any other core WordPress files. Hacking core files is a bad idea because upgrading to a new version of WordPress will override your changes. The only directory you should need to interact with is wp-content because it contains your plugins, themes, and uploaded files.

Any time you find yourself wanting to hack a core WordPress file, think again. There is probably a hook or filter you could use to accomplish the same goal. If there isn’t a hook or filter available to do what you need, add one and request to have it added to the core. The core WordPress developers are very responsive about adding in new hooks and filters.

There is one more file you may need to update in the WordPress root directory, depending on your setup and how you are using WordPress: the .htaccess file. It’s not a WordPress core file, but an Apache file WordPress uses to handle directory configuration, permalinks, and redirects. This file is not there by default; it’s created by WordPress automatically the first time you define your permalink structure. Check out all the .htaccess configuration options at your leisure on WordPress’s htaccess Support page.

/wp-admin

This directory contains core directories and files for managing the WordPress admin dashboard interface. A key file in this directory is admin-ajax.php, which all Ajax requests should be run through. We cover Ajax in Chapter 9.

/wp-includes

This directory contains core directories and files for various WordPress functionality. We highly encourage you to look over the structure and code in this directory to better understand the inner workings of WordPress.

/wp-content

This directory is where WordPress users and developers can make WordPress do whatever they want. It contains subdirectories for the plugins and themes you have installed on your website as well as any media files you upload to your website.

The wp-content directory includes several subdirectories, as described next.

/wp-content/plugins

Any WordPress plugin you install on your WordPress site will be located in this directory. By default, WordPress comes with the Hello Dolly and Akismet plugins.

Hello Dolly is included as a quick example of how a basic WordPress plugin is set up. The plugin itself just displays a random line from the song “Hello Dolly” in the upper right of the administrator dashboard.

The Akismet plugin helps stop spam comments by checking incoming comments against the database at https://akismet.com. This plugin and service greatly reduce the number of spam comments that make it onto the frontend of your website. The Akismet service is free (or name your own price) for personal use.

/wp-content/themes

Any WordPress themes you install on your WordPress site will be located in this directory. By default, WordPress comes with a few standard themes all named for the year they were released (Twenty Seventeen, Twenty Nineteen, etc.).

/wp-content/uploads

Once you start uploading any photos or files to your media library, you will see this directory being populated with those uploaded files. All uploaded media is stored in the uploads directory. Some plugins will also create a subdirectory in the uploads directory to various files used or managed by the plugin.

/wp-content/mu-plugins

In WordPress, you can force the use of any plugin by creating a mu-plugins directory inside of the wp-content directory. This directory does not exist unless you create it. The “mu” stands for “must use,” and any plugin you put in the mu-plugins folder will automatically run without needing to be manually activated on the admin plugins page. In fact, you won’t even see any must-use plugins listed there.

Must-use plugins are especially useful on multisite installs of WordPress so you can use plugins that your individual network site admins won’t be able to deactivate.

It is a good idea to check for the mu-plugins folder on any existing site you start working on to see whether it contains any plugins, and if so, to determine what they do. So many times we have been debugging an issue and wondering why something unexpected was happening even though we had disabled all of the active plugins, only to find out that there was an overlooked mu-plugin responsible for the issue.

WordPress Database Structure

WordPress runs on top of a MySQL database and creates its own tables to store data and content. Following is the database schema created by a default installation of WordPress. We have also included some basic information on built-in WordPress functions for interacting with these tables. If you can grasp the database schema and get comfortable with the list functions in this chapter, you can push and pull any data into and out of WordPress.

Note

The following table names use the default prefix wp_. You can change this prefix during the WordPress installation; thus, the exact table names of your WordPress install may vary.

wp_options

The wp_options table stores any sitewide data for you. This table stores the name, description, and admin email that you entered when running a typical installation. This table will also come prepopulated with a few records that store the various default settings within WordPress. Table 2-1 shows the database structure for the wp_options table.

Table 2-1. Database schema for wp_options table
Column Type Collation Null Default Extra

option_id

bigint(20)

No

None

AUTO_INCREMENT

option_name

varchar(64)

utf8_general_ci

No

option_value

longtext

utf8_general_ci

No

None

autoload

varchar(20)

utf8_general_ci

No

Yes

WordPress apps and plugins typically store their settings in the wp_options table using the functions defined in the next section. The settings can be stored in separate rows while using a common prefix for the option names. In most cases, it is more performant to store all of the options in one array and save them into just one row in the wp_options table.

Functions Found in /wp-includes/option.php

The following functions can be found in /wp-includes/option.php.

add_option( string $option, mixed $value = '', string $deprecated = '', string|bool $autoload = ‘yes’ )

First checks whether an option_name exists before inserting a new row:

$option

A required string of the option_name you would like to add.

$value

An optional mixed variable of the option_value you would like to add. If the variable passed is an array or object, the value will be serialized before storing in the database.

$deprecated

This parameter, deprecated in version 2.3, is no longer used.2

$autoload

An optional Boolean used to distinguish whether to load the option into cache when WordPress starts up. Set to yes or no. The default value is yes. If you are sure you are going to need this option on every page load, you can leave the value as the default yes. If you are only going to need to look up the option on specific pages, it’s usually better to set autoload to no.

update_option( $option, $newvalue )

Updates an existing option but will also add it if it doesn’t already exist:

$option

A required string of the option_name you would like to update/add.

$newvalue

An optional mixed variable of the option_value you would like to update/add.

get_option( $option, $default = false )

Retrieves the option_value for a provided option_name:

$option

A required string of the option_name you would like to get.

$default

An optional mixed variable you would like to return if the option_name you provided doesn’t exist in the table. By default, this parameter is false.

delete_option( $option )

Deletes an existing option from the database permanently:

$option

A required string of the option_name you would like to delete.

Note

Most code examples in this book are not fully functional code, but basic theoretical examples of how to use the functions we are talking about. You can follow along with most of the code examples in a custom plugin or your theme’s functions.php file.

Example 2-1 demonstrates some basic functions for interacting with the wp_options table.

Example 2-1. Adding, updating, getting, and deleting records in the wp_options table
<?php
// add option
$twitters = array( '@bwawwp', '@bmess', '@jason_coleman' );
add_option( 'bwawwp_twitter_accounts', $twitters );

// get option
$bwawwp_twitter_accounts = get_option( 'bwawwp_twitter_accounts' );
echo '<pre>';
print_r( $bwawwp_twitter_accounts );
echo '</pre>';

// update option
$twitters = array_merge(
         $twitters,
         array(
                 '@alphaweb',
                 '@pmproplugin'
         )
);
update_option( 'bwawwp_twitter_accounts', $twitters );

// get option
$bwawwp_twitter_accounts = get_option( 'bwawwp_twitter_accounts' );
echo '<pre>';
print_r( $bwawwp_twitter_accounts );
echo '</pre>';

// delete option
delete_option( 'bwawwp_twitter_accounts' );


/*
The output from the above example should look something like this:
Array
(
    [0] => @bwawwp
    [1] => @bmess
    [2] => @jason_coleman
)
Array
(
    [0] => @bwawwp
    [1] => @bmess
    [2] => @jason_coleman
    [3] => @alphaweb
    [4] => @pmproplugin
)
*/
?>

wp_users

When you log in to WordPress with your username and password, you are referencing data stored in this table. All users and their default data are stored in the wp_users table. Table 2-2 shows the database structure for the wp_users table.

Table 2-2. Database schema for wp_users table
Column Type Collation Null Default Extra

ID

bigint(20)

No

None

AUTO_INCREMENT

user_login

varchar(60)

utf8_general_ci

No

user_pass

varchar(64)

utf8_general_ci

No

user_nicename

varchar(50)

utf8_general_ci

No

user_email

varchar(100)

utf8_general_ci

No

user_url

varchar(100)

utf8_general_ci

No

user_registered

datetime

No

0000-00-00 00:00:00

user_activation_key

varchar(60)

utf8_general_ci

No

user_status

int(11)

No

0

display_name

varchar(250)

utf8_general_ci

No

For many WordPress apps, you will use the administrator dashboard GUI to create and manage users. However, if you need to create users in your code or update metadata about them, the functions defined in the next section will be useful.

Functions Found in /wp-includes/…

These functions are found in /wp-includes/pluggable.php and /wp-includes/user.php.

wp_insert_user( $userdata )

Inserts a new user into the database. This function can also be used to update a user if the user ID is passed in with the $user_data. $userdata is a required array of field names and values. Accepted fields are as follows:

ID

An integer that will be used for updating an existing user.

user_pass

A string that contains the plain-text password for the user.

user_login

A string that contains the user’s username for logging in.

user_nicename

A string that contains a URL-friendly name for the user. The default is the user’s username.

user_url

A string containing the URL for the user’s website.

user_email

A string containing the user’s email address.

display_name

A string that will be shown on the site. Defaults to the user’s username. It is likely that you will want to change this, for appearance.

nickname

The user’s nickname. Defaults to the user’s username.

first_name

The user’s first name.

last_name

The user’s last name.

description

A string containing content about the user.

rich_editing

A string for whether to enable the rich editor. false if not empty.

user_registered

The date the user registered. Format is Y-m-d H:i:s.

role

A string used to set the user’s role.

wp_create_user( $username, $password, $email )

This function utilizes the prior function wp_insert_user() and makes it easier to add a new user based on the required columns:

$username

A required string of the username/login of a new user.

$password

A required string of the password of a new user.

$email

A required string of the email address of a new user.

wp_update_user( $userdata )

Use this function to update any field in the wp_users and wp_usermeta (covered next) tables tied to a specific user. Note that if a user’s password is updated, all of their cookies will be cleared, logging them out of WordPress:

$userdata

A required array of field names and values. The ID and at least one other field is required. These fields are the same ones accepted in the wp_insert_post() function.

get_user_by( $field, $value )

This function returns the WP_User object on success and false if it fails. The WordPress User class is found in /wp-includes/capabilities.php and basically queries the wp_user table like so:

SELECT * FROM wp_users WHERE $field = $value;

The WP_User class caches the results to avoid querying the database every time it is used. The class also figures out the roles and capabilities of a specific user, which we will go over in more detail in Chapter 6:

$field

A required string of the field by which you would like to query the user data. This string can only be id, slug, email, or login.

$value

A required integer or string of the value for a given id, slug, email, or login.

get_userdata( $userid )

This function actually utilizes the previous function, get_user_by(), and returns the same WP_User object:

$userid

A required integer of the user ID of the user for which you would like to get data.

wp_delete_user( $id, $reassign = ‘novalue’ )

You guessed it: this function delete a user and can also reassign any of their posts or links to another user:

$id

A required integer of the ID of the user you would like to delete.

$reassign

An optional integer of the ID you would like to reassign any post or links from the deleted user to. Example 2-2 demonstrates some of the basic functions for interacting with the wp_users table.

Example 2-2. Working with the wp_users table
<?php
// insert user
$userdata = array(
    'user_login'    => 'brian',
	'user_pass'     => 'KO03gT7@n*',
	'user_nicename' => 'Brian',
	'user_url'      => 'https://alphaweb.com/',
	'user_email'    => '[email protected]',
	'display_name'  => 'Brian',
	'nickname'      => 'Brian',
	'first_name'    => 'Brian',
	'last_name'     => 'Messenlehner',
	'description'   => 'This is a WordPress Administrator account.',
	'role'          => 'administrator'
);
wp_insert_user( $userdata );

// create users
wp_create_user( 'jason', 'YR529G%*v@', '[email protected]' );

// get user by login
$user = get_user_by( 'login', 'brian' );
echo 'email: ' . $user->user_email  . ' / ID: ' . $user->ID . '<br>';
echo 'Hi: ' . $user->first_name . ' ' . $user->last_name . '<br>';

// get user by email
$user = get_user_by( 'email', '[email protected]' );
echo 'username: ' . $user->user_login . ' / ID: ' . $user->ID . '<br>';

// update user-change username fields and change role to admin
$userdata = array(
	'ID'         => $user->ID,
	'first_name' => 'Jason',
	'last_name'  => 'Coleman',
	'user_url'   => 'http://strangerstudios.com/',
	'role'       => 'administrator'
);
wp_update_user( $userdata );

// get userdata for brian
$user = get_userdata( $user->ID );
echo 'Hi: ' . $user->first_name . ' ' . $user->last_name . '<br>';

// delete user-delete the original admin and set their posts to our new admin
// wp_delete_user( 1, $user->ID );

/*
The output from the above example should look something like this:
email: [email protected] / ID: 2
Hi: Brian Messenlehner
username: jason / ID: 3
Hi: Jason Coleman
*/
?>

wp_usermeta

Sometimes you may want to store additional data along with a user. WordPress provides an easy way to do this without having to add extra columns to the users table. You can store as much user metadata as you need to in the wp_usermeta table. Each record is associated to a user ID in the wp_user table by the user_id field. Table 2-3 shows the database structure for the wp_usermeta table.

Table 2-3. Database schema for wp_usermeta table
Column Type Collation Null Default Extra

umeta_id

bigint(20)

No

None

AUTO_INCREMENT

user_id

bigint(20)

No

0

meta_key

varchar(255)

utf8_general_ci

Yes

NULL

meta_value

longtext

utf8_general_ci

Yes

NULL

get_user_meta( $user_id, $key = '', $single = false )

Gets a user’s meta value for a specified key:

$user_id

A required integer of a user ID.

$key

An optional string of the meta key of the value you would like to return. If blank, then all metadata for the given user will be returned.

$single

A Boolean of whether to return a single value or not. The default is false and the value will be returned as an array.

There can be more than one meta key for the same user ID with different values. If you set $single to true, you will get the first key’s value; if you set it to false, you will get an array of the values of each record with the same key.

update_user_meta( $user_id, $meta_key, $meta_value, $prev_value = '' )

This function will update user metadata but will also insert metadata if the passed-in key doesn’t already exist:

$user_id

A required integer of a user ID.

$meta_key

A required string of the meta key name for the meta value you would like to store. If this meta key already exists, it will update the current row’s meta value; if not, it will insert a new row.

$meta_value

A required mixed value of an integer, string, array, or object. Arrays and objects will automatically be serialized.

$prev_value

An optional mixed value of the current metadata value. If a match is found, it will replace the previous/current value with the new value you specified. If left blank, the new meta value will replace the first instance of the matching key. If you have five rows of metadata with the same key and you don’t specify which row to update with this value, it will update the first row and remove the other four.

Note

This function relies on the update_metadata() function located in /wp-includes/meta.php. Check it out!

add_user_meta( $user_id, $meta_key, $meta_value, $unique = false )

Yup, this function will insert brand-new user meta into the wp_usermeta table. We don’t use this function often anymore because we can just use update_user_meta() to insert new rows as well as update them. If you want to ensure that a given meta key is used only once per user, you should use this function and set the $unique parameter to true:

$user_id

A required integer of a user ID.

$meta_key

A required string of the meta key name for the meta value you would like to store.

$meta_value

A required mixed value of an integer, string, array, or object.

$unique

An optional Boolean that, when set to true, will make sure the meta key can only ever be added once for a given ID.

delete_user_meta( $user_id, $meta_key, $meta_value = '' )

Deletes user metadata for a provided user ID and matching key. You can also specify a matching meta value if you want to delete only that value and not other metadata rows with the same meta key:

$user_id

A required integer of a user ID.

$meta_key

A required string of the meta key name for the meta value you would like to delete.

$meta_value

An optional mixed value of the meta value. If you have more than one record with the same meta key, you can specify which one to delete by matching the meta value. It defaults to nothing, which will delete all meta rows with a matching user_id and meta_key.

Example 2-3 demonstrates some of the basic functions for interacting with the wp_username table.

Example 2-3. Working with the wp_username table
<?php
// get brian's id
$brian_id = get_user_by( 'login', 'brian' )->ID;

// add user meta - unique is set to true.
add_user_meta( $brian_id, 'bwawwp_wife', 'Married to the game', true);

// get user meta - returning a single value
$brians_wife = get_user_meta( $brian_id, 'bwawwp_wife', true);
echo "Brian's wife: " . $brians_wife . "<br>";

// add user meta - 3rd parameter is a unique value
add_user_meta( $brian_id, 'bwawwp_kid', 'Dalya' );
add_user_meta( $brian_id, 'bwawwp_kid', 'Brian' );
add_user_meta( $brian_id, 'bwawwp_kid', 'Nina' );
add_user_meta( $brian_id, 'bwawwp_kid', 'Cam' );
add_user_meta( $brian_id, 'bwawwp_kid', 'Aksel' );

// update user meta - this will update brian to brian jr.
update_user_meta( $brian_id, 'bwawwp_kid', 'Brian Jr', 'Brian' );

// get user meta - returning an array
$brians_kids = get_user_meta( $brian_id, 'bwawwp_kid' );
echo "Brian's kids:";
echo '<pre>';
print_r($brians_kids);
echo '</pre>';

// delete brian's user meta
delete_user_meta( $brian_id, 'bwawwp_wife' );
delete_user_meta( $brian_id, 'bwawwp_kid' );

// get jason's id
$jason_id = get_user_by( 'login', 'jason' )->ID;

// update user meta - this will create meta if the key doesn't exist for the user.
update_user_meta( $jason_id, 'bwawwp_wife', 'Kimberly Ann Coleman' );

// get user meta-returning an array
$jasons_wife = get_user_meta( $jason_id, 'bwawwp_wife' );
echo "Jason's wife:";
echo '<pre>';
print_r($jasons_wife);
echo '</pre>';

// add user meta - storing as an array
add_user_meta( $jason_id, 'bwawwp_kid', array( 'Isaac', 'Marin' ) );

// get user meta - returning a single value which happens to be an array.
$jasons_kids = get_user_meta( $jason_id, 'bwawwp_kid', true );
echo "Jason's kids:";
echo '<pre>';
print_r($jasons_kids);
echo '</pre>';

// delete jason's user meta
delete_user_meta( $jason_id, 'bwawwp_wife' );
delete_user_meta( $jason_id, 'bwawwp_kid' );

/*
The output from the above example should look something like this:
Brian's wife: Married to the game
Brian's kids:
Array
(
    [0] => Dalya
    [1] => Brian Jr
    [2] => Nina
    [3] => Cam
    [4] => Aksel
)
Jason's wife:
Array
(
    [0] => Kimberly Ann Coleman
)
Jason's kids:
Array
(
    [0] => Isaac
    [1] => Marin
)
*/
?>

wp_posts

Ah, the meat of WordPress. The wp_posts table is where most of your post data is stored. By default, WordPress comes with posts and pages. Both of these are technically posts and are stored in this table. The post_type field is what distinguishes the type of a post—that is, whether it is a post, a page, a menu item, a revision, or any CPT that you may later create (CPTs are covered more in Chapter 5). Table 2-4 shows the database structure for the wp_posts table.

Table 2-4. Database schema for wp_posts table
Column Type Collation Null Default Extra

ID

bigint(20)

No

None

AUTO_INCREMENT

post_author

bigint(20)

No

0

post_date

datetime

No

0000-00-00 00:00:00

post_date_gmt

datetime

No

0000-00-00 00:00:00

post_content

longtext

utf8_general_ci

No

None

post_title

text

utf8_general_ci

No

None

post_excerpt

text

utf8_general_ci

No

None

post_status

varchar(20)

utf8_general_ci

No

Publish

comment_status

varchar(20)

utf8_general_ci

No

Open

ping_status

varchar(20)

utf8_general_ci

No

Open

post_password

varchar(20)

utf8_general_ci

No

post_name

varchar(200)

utf8_general_ci

No

to_ping

text

utf8_general_ci

No

None

pinged

text

utf8_general_ci

No

None

post_modified

datetime

No

0000-00-00 00:00:00

post_modified_gmt

datetime

No

0000-00-00 00:00:00

post_content_filtered

longtext

utf8_general_ci

No

None

post_parent

bigint(20)

No

0

guid

varchar(255)

utf8_general_ci

No

menu_order

int(11)

No

0

post_type

varchar(20)

utf8_general_ci

No

Post

post_mime_type

varchar(100)

utf8_general_ci

No

comment_count

bigint(20)

No

0

Functions Found in /wp-includes/post.php

The functions that follow are found in /wp-includes/post.php.

wp_insert_post( $postarr, $wp_error = false )

This function inserts a new post with provided post data:

$postarr

An array or object of post data. Arrays are expected to be escaped; objects are not.

$wp_error

An optional Boolean that will allow for a WP_Error if returned false.

The defaults for the parameter $postarr are:

post_status

Default is draft.

post_type

Default is post.

post_author

Default is current user ID ($user_ID). The ID of the user who added the post.

ping_status

Default is the value in the default_ping_status option. Whether the attachment can accept pings.

post_parent

Default is 0. Set this for the post it belongs to, if any.

menu_order

Default is 0. The order in which the array is displayed.

to_ping

Whether to ping.

pinged

Default is empty string.

post_password

Default is empty string. The password to access the attachment.

guid

Global unique ID for referencing the attachment.

post_content_filtered

Post content filtered.

post_excerpt

Post excerpt.

wp_update_post( $postarr = array(), $wp_error = false )

This function updates a post with provided post data.

$postarr

A required array or object of post data. Arrays are expected to be escaped; objects are not.

$wp_error

An optional Boolean that will allow for a WP_Error if returned false.

get_post( $post = null, $output = OBJECT, $filter = ‘raw’ )

This function gets post data from a provided post ID or a post object:

$post

An optional integer or object of the post ID or post object you want to retrieve. The default is the current post you are on inside of the post loop, which is covered later in this chapter.

$output

An optional string of the output format. The default value is OBJECT (WP_Post object) and the other values can be ARRAY_A (associative array) or ARRAY_N (numeric array).

$filter

An optional string of how the context should be sanitized on output. The default value is raw, but other values can be edit, db, display, attribute, or js. Sanitization is covered in Chapter 8.

get_posts( $args = null )

This function returns a list of posts from matching criteria. This function uses the WP_Query class, which you will see examples of throughout the book: $args is an optional array of post arguments. The defaults are:

numberposts

Default is 5. Total number of posts to retrieve. –1 is all.

offset

Default is 0. Number of posts to pass over.

category

What category to pull the posts from.

orderby

Default is post_date. How to order the posts.

order

Default is DESC. The order to retrieve the posts.

include

A list of post IDs to include.

exclude

A list of post IDs to exclude.

meta_key

Any metadata key.

meta_value

Any metadata value. Must also use meta_key.

post_type

Default is post. Can be page, or attachment, or the slug for any custom CPT. The string any will return posts from all post types.

post_parent

The parent ID of the post.

post_status

Default is publish. Post status to retrieve.

wp_delete_post( $postid = 0, $force_delete = false )

This function will trash any post or permanently delete it if $force_delete is set to true:

$postid

A required integer of the post ID you would like to trash or delete.

$force_delete

An optional Boolean that, if set to true, will delete the post; if left blank, it will default to false and move the post to a deleted status.

Example 2-4 demonstrates some of the basic functions for interacting with the wp_posts table.

Example 2-4. Working with the wp_posts table
<?php
// insert post - set post status to draft
$args = array(
	'post_title'   => 'Building Web Apps with WordPress',
	'post_excerpt' => 'WordPress as an Application Framework',
	'post_content' => 'WordPress is the key to successful cost effective
	web solutions in most situations. Build almost anything on top of the
	WordPress platform. DO IT NOW!!!!',
	'post_status'  => 'draft',
	'post_type'    => 'post',
	'post_author'  => 1,
	'menu_order'   => 0
);
$post_id = wp_insert_post( $args );
echo 'post ID: ' . $post_id . '<br>';

// update post - change post status to publish
$args = array(
	'ID'  => $post_id,
	'post_status' => 'publish'
);
wp_update_post( $args );

// get post - return post data as an object
$post = get_post( $post_id );
echo 'Object Title: ' . $post->post_title . '<br>';

// get post - return post data as an array
$post = get_post( $post_id, ARRAY_A );
echo 'Array Title: ' . $post['post_title'] . '<br>';

// delete post - skip the trash and permanently delete it
wp_delete_post( $post_id, true );

// get posts - return 100 posts
$posts = get_posts( array( 'numberposts' => '100') );
// loop all posts and display the ID & title
foreach ( $posts as $post ) {
	echo $post->ID . ': ' .$post->post_title . '<br>';
}

/*
The output from the above example should look something like this:
post ID: 589
Object Title: Building Web Apps with WordPress
Array Title: Building Web Apps with WordPress
"A list of post IDs and Titles from your install"
*/
?>

wp_postmeta

At times you may want to store additional data along with a post. WordPress provides an easy way to do this without having to add extra fields to the posts table. You can store as much post metadata as you need to in the wp_postmeta table. Each record is associated to a post through the post_id field. When editing any post in the backend of WordPress, you can add/update/delete metadata or custom fields via the UI. Table 2-5 shows the database structure for the wp_postmeta table.

Note

Metadata keys that start with an underscore are hidden from the Custom Fields UI on the edit post page. This is useful to hide certain meta fields that you don’t want end users editing directly.

Table 2-5. Database schema for wp_postmeta table
Column Type Collation Null Default Extra

meta_id

bigint(20)

No

None

AUTO_INCREMENT

post_id

bigint(20)

No

0

meta_key

varchar(255)

utf8_general_ci

Yes

NULL

meta_value

longtext

utf8_general_ci

Yes

NULL

Functions Found in /wp-includes/post.php

The following functions are found in /wp-includes/post.php.

get_post_meta( $post_id, $key = '', $single = false )

Get post metadata for a given post:

$post_id

A required integer of the post ID, for which you would like to retrieve post meta.

$key

Optional string of the meta key name for which you would like to retrieve post meta. The default is to return metadata for all of the meta keys for a particular post.

$single

A Boolean of whether to return a single value or not. The default is false, and the value will be returned as an array.

There can be more than one meta key for the same post ID with different values. If you set $single to true, you will get the first key’s value; if it is set to false, you will get an array of the values of each record with the same key.

update_post_meta( $post_id, $meta_key, $meta_value, $prev_value = '' )

This function updates post metadata, but it also inserts metadata if the passed-in key doesn’t already exist:

$post_id

A required integer of a post ID.

$meta_key

A required string of the meta key name for the meta value you would like to store. If this meta key already exists, it will update the current row’s meta value; if not, it will insert a new row.

$meta_value

A required mixed value of an integer, string, array, or object. Arrays and objects will automatically be serialized.

$prev_value

An optional mixed value of the current metadata value. If a match is found, it will replace the previous/current value with the new value you specified. If left blank, the new meta value will replace the first instance of the matching key. If you have five rows of metadata with the same key and you don’t specify which row to update with this value, it will update the first row and remove the other four.

Note

This function relies on the update_metadata() function located in /wp-includes/meta.php. Check it out!

add_post_meta( $post_id, $meta_key, $meta_value, $unique = false )

This function inserts brand-new post meta into the wp_postmeta table. This function is used less these days because we can just use the previous function we talked about, update_post_meta(), to insert new rows as well as update them. If you want to ensure that a given meta key is used only once per post, you should use this function and set the $unique parameter to true:

$user_id

A required integer of a post ID.

$meta_key

A required string of the meta key name for the meta value you would like to store.

$meta_value

A required mixed value of an integer, string, array, or object.

$unique

An optional Boolean that, when set to true, will ensure that the meta key can be added only once for a given ID.

delete_post_meta( $post_id, $meta_key, $meta_value = '' )

This function deletes post metadata for a provided post ID and matching key. You can also specify a matching meta value if you want to delete only that value and not other metadata rows with the same meta key:

$post_id

A required integer of a post ID.

$meta_key

A required string of the meta key name for the meta value you would like to delete.

$meta_value

An optional mixed value of the meta value. If you have more than one record with the same meta key, you can specify which one to delete by matching this value. It defaults to nothing, which will delete all meta rows with a matching post_id and meta_key.

In Example 2-5, we get the last post and add, update, and delete various post meta.

Example 2-5. Working with post metadata
<?php
// get posts - return the latest post
$posts = get_posts( array( 'numberposts' => '1', 'orderby' =>
    'post_date', 'order' => 'DESC' ) );
foreach ( $posts as $post ) {
	$post_id = $post->ID;

	// update post meta - public metadata
	$content = 'You SHOULD see this custom field when editing your latest post.';
	update_post_meta( $post_id, 'bwawwp_displayed_field', $content );

	// update post meta - hidden metadata
	$content = str_replace( 'SHOULD', 'SHOULD NOT', $content );
	update_post_meta( $post_id, '_bwawwp_hidden_field', $content );

	// array of student logins
	$students[] = 'dalya';
	$students[] = 'ashleigh';
	$students[] = 'lola';
	$students[] = 'isaac';
	$students[] = 'marin';
	$students[] = 'brian';
	$students[] = 'nina';
 $students[] = 'cam';

	// add post meta - one key with array as value, array will be serialized
    // automatically
	add_post_meta( $post_id, 'bwawwp_students', $students, true );

	// loop students and add post meta record for each student
	foreach ( $students as $student ) {
		add_post_meta( $post_id, 'bwawwp_student', $student );
	}

	// get post meta - get all meta keys
	$all_meta = get_post_meta( $post_id );
	echo '<pre>';
	print_r( $all_meta );
	echo '</pre>';

	// get post meta - get 1st instance of key
	$student = get_post_meta( $post_id, 'bwawwp_student', true );
	echo 'oldest student: ' . $student;

	// delete post meta
	delete_post_meta( $post_id, 'bwawwp_student' );
}

/*
The output from the above example should look something like this:
Array
(
    [_bwawwp_hidden_field] => Array
        (
        [0] => You SHOULD NOT see this custom field when editing your latest post.
        )

    [bwawwp_displayed_field] => Array
        (
            [0] => You SHOULD see this custom field when editing your latest post.
        )

    [bwawwp_students] => Array
        (
        [0] => a:7:{i:0;s:5:"dalya";i:1;s:8:"ashleigh";i:2;s:4:"lola";i:3;s:5:
        "isaac";i:4;s:5:"marin";i:5;s:5:"brian";i:6;s:4:"nina";i:6;s:5:"cam";}
        )

    [bwawwp_student] => Array
        (
            [0] => dalya
            [1] => ashleigh
            [2] => lola
            [3] => isaac
            [4] => marin
            [5] => brian
            [6] => nina
	[7] => cam
        )
)
oldest student: dalya
*/
?>

wp_comments

Comments can be left on any post. The wp_comments table stores individual comments and associated comment data for any post. Table 2-6 shows the database structure for the wp_comments table.

Table 2-6. Database schema for wp_comments table
Column Type Collation Null Default Extra

comment_ID

bigint(20)

No

None

AUTO_INCREMENT

comment_post_ID

bigint(20)

No

0

comment_author

tinytext

utf8_general_ci

No

comment_author_email

varchar(100)

utf8_general_ci

No

comment_author_url

varchar(200)

utf8_general_ci

No

comment_author_IP

varchar(100)

utf8_general_ci

No

comment_date

datetime

No

0000-00-00 00:00:00

comment_date_gmt

datetime

No

0000-00-00 00:00:00

comment_content

text

utf8_general_ci

No

None

comment_karma

int(11)

No

0

comment_approved

varchar(20)

utf8_general_ci

No

1

comment_agent

varchar(20)

utf8_general_ci

No

comment_type

varchar(20)

utf8_general_ci

No

comment_parent

bigint(20)

No

0

user_id

bigint(20)

No

0

Functions Found in /wp-includes/comment.php

The functions that follow are found in /wp-includes/comment.php.

get_comment( $comment, $output = OBJECT )

This function returns comment data from a comment ID or comment object. If the comment is empty, the global comment variable will be used if set:

$comment

An optional integer, string, or object of a comment ID or object.

$output

An optional string that defines what format the output should be in. Possible values are OBJECT, ARRAY_A, and ARRAY_N.

get_comments( $args = '' )

This function retrieves a list of comments for specific posts or a single post. It calls the WP_Comment_Query class, which we cover in the next chapter. $args are an optional array or string of arguments to query comments. The default arguments are:

author_email

A string of a comment author’s email address.

ID

An integer of the ID of a comment.

karma

An integer of a comment’s karma, which can be used by plugins for rating.

number

An integer of the number of comments to return. Default is all comments.

offset

An integer of the number of comments to pass over. Default is 0.

orderby

A string of the field in which to order the comment by. Allowed values are: comment_agent, comment_approved, comment_author, comment_author_email, comment_author_IP, comment_author_url, comment_content, comment_date, comment_date_gmt, comment_ID, comment_karma, comment_parent, comment_post_ID, comment_type, and user_id.

order

A string of how to order the selected orderby argument. Defaults to DESC and also accepts ASC.

parent

An integer of a comment’s parent comment ID.

post_id

An integer of the post ID to which a comment is attached.

post_author

An integer of the post author ID to which a comment is attached.

post_name

A string of the post name to which a comment is attached.

post_parent

An integer of the post parent ID to which a comment is attached.

post_status

A string of the post status to which a comment is attached.

post_type

A string of the post type to which a comment is attached.

status

A string of the status of a comment. Optional values are hold, approve, spam, or trash.

type

A string of the type of a comment. Optional values are '', pingback, or trackback.

user_id

An integer of the user ID of a comment.

search

A string of search terms on which you can search a comment. Searches the following fields: comment_author, comment_author_email, comment_author_url, comment_author_IP, and comment_content.

count

A Boolean that will make the query return a count or results. The default value is false.

meta_key

The comment meta key of comment meta to search on.

meta_value

The comment meta value of comment meta to search on; meta_key is required.

wp_insert_comment( $commentdata )

This function inserts a comment into the database:

$commentdata

A required array of comment fields and values to be inserted. Available fields to be inserted are: comment_post_ID, comment_author, comment_author_email, comment_author_url, comment_author_IP, comment_date, comment_date_gmt, comment_content, comment_karma, comment_approved, comment_agent, comment_type, comment_parent, and user_id.

wp_update_comment( $commentarr )

This function updates comment data and filters to make sure all required fields are valid before updating in the database:

$commentarr

An optional array of arguments containing comment fields and values to be updated. These are the same field arguments just listed for the wp_insert_comment() function.

wp_delete_comment( $comment_id, $force_delete = false )

This function deletes a comment. By default, it will trash the comment unless you specify to permanently delete:

$comment_id

A required integer of the comment ID to trash/delete.

$force_delete

An optional Boolean that if set to true will permanently delete a comment. Example 2-6 demonstrates some of the basic functions for interacting with the wp_comments table.

Example 2-6 demonstrates managing comment data attached to a post.

Example 2-6. Working with the wp_comments table
<?php
// insert post
$args = array(
 'post_title'   => 'What should I do tonight?',
 'post_content' => 'Think of something cool to do and make a comment about it!',
 'post_status'  => 'publish'
);
$post_id = wp_insert_post( $args );
echo 'post ID: ' . $post_id . ' - ' . $args['post_title'] . '<br>';

// make comments array
$comments[] = 'ICE CREAM!!!!';
$comments[] = 'Taco Bell';
$comments[] = 'Get a good night sleep';

//loop comments array
foreach ( $comments as $key => $comment ) {
	// insert comments
	$commentdata = array(
		'comment_post_ID' => $post_id,
		'comment_content' => $comments[$key],
	);
	$comment_ids[] = wp_insert_comment( $commentdata );
}
echo 'comments:<pre>';
print_r( $comments );
echo '</pre>';

// update comment
$commentarr['comment_ID'] = $comment_ids[0];
$commentarr['comment_content'] = 'Read this entire book';
wp_update_comment( $commentarr );

// insert comment - sub comment from parent id
$commentdata = array(
	'comment_post_ID' => $post_id,
	'comment_parent' => $comment_ids[0],
	'comment_content' => 'That is a pretty good idea...',
);
wp_insert_comment( $commentdata );

// get comments - search taco bell
$comments = get_comments( 'search=Taco Bell&number=1' );
foreach ( $comments as $comment ) {
	// insert comment - sub comment of taco bell comment id
	$commentdata = array(
		'comment_post_ID' => $post_id,
		'comment_parent' => $comment->comment_ID,
		'comment_content' => ',
	);
	wp_insert_comment( $commentdata );
}

// get comment - count of comments for this post
$comment_count = get_comments( 'post_id= ' . $post_id . '&count=true' );
echo 'comment count: ' . $comment_count . '<br>';

// get comments - get all comments for this post
$comments = get_comments( 'post_id=' .$post_id );
foreach ( $comments as $comment ) {
	// update 1st comment
	if ( $comment_ids[0] == $comment->comment_ID ) {
	 $commentarr = array(
	  'comment_ID' => $comment->comment_ID,
	  'comment_content' => $comment->comment_content . ' & build some apps!',
	);
		wp_update_comment( $commentarr );
		// delete all other comments
	}else {
		// delete comment
		wp_delete_comment( $comment->comment_ID, true );
	}
}

// get comment - new comment count
$comment_count = get_comments( 'post_id= ' . $post_id . '&count=true' );
echo 'new comment count: ' . $comment_count . '<br>';

// get comment - get best comment
$comment = get_comment( $comment_ids[0] );
echo 'best comment: ' . $comment->comment_content;

/*
The output from the above example should look something like this:
post ID: 91011 - What should I do tonight?
comments:
Array
(
    [0] => ICE CREAM!!!!
    [1] => Taco Bell
    [2] => Get a good night sleep
)
comment count: 5
new comment count: 1
best comment: Read this entire book & build some apps!
*/
?>

wp_commentsmeta

Just like the wp_usermeta and wp_postmeta table, this table stores any custom, additional data tied to a comment by the comment_id fields. Table 2-7 shows the database structure for the wp_commentsmeta table.

Table 2-7. Database schema for wp_commentsmeta table
Column Type Collation Null Default Extra

meta_id

bigint(20)

No

None

AUTO_INCREMENT

comment_id

bigint(20)

No

0

meta_key

varchar(255)

utf8_general_ci

Yes

NULL

meta_value

longtext

utf8_general_ci

Yes

NULL

Functions Found in /wp-includes/comment.php

The following functions are found in /wp-includes/comment.php.

get_comment_meta( $comment_id, $key = '', $single = false )

This function gets comment meta for a given comment ID:

$comment_id

A required integer of the comment ID for which you would like to retrieve comment meta.

$key

Optional string of the meta key name for which you would like to retrieve comment meta. The default is to return metadata for all of the meta keys for a particular post.

$single

A Boolean of whether to return a single value or not. The default is false, and the value will be returned as an array.

add_comment_meta( $comment_id, $meta_key, $meta_value, $unique = false )

This function adds comment meta for given comment ID:

$comment_id

A required integer of a comment ID.

$meta_key

A required string of the meta key name for the meta value you would like to store.

$meta_value

A required mixed value of an integer, string, array, or object.

$unique

An optional Boolean that, when set to true, will make sure the meta key can only ever be added once for a given ID.

update_comment_meta( $comment_id, $meta_key, $meta_value, $prev_value = '' )

This function updates comment meta for a given comment ID:

$comment_id

A required integer of a comment ID.

$meta_key

A required string of the meta key name for the meta value you would like to store. If this meta key already exists, it will update the current row’s meta value; if not, it will insert a new row.

$meta_value

A required mixed value of an integer, string, array, or object. Arrays and objects will automatically be serialized.

$prev_value

An optional mixed value of the current metadata value. If a match is found, it will replace the previous/current value with the new value you specified. If left blank, the new meta value will replace the first instance of the matching key. If you have five rows of metadata with the same key and you don’t specify which row to update with this value, it will update the first row and remove the other four.

delete_comment_meta( $comment_id, $meta_key, $meta_value = '' )

This function deletes comment metadata for a provided comment ID and matching key. You can also specify a matching meta value if you only want to delete that value and not other metadata rows with the same meta key:

$comment_id

A required integer of a comment ID.

$meta_key

A required string of the meta key name for the meta value you would like to delete.

$meta_value

An optional mixed value of the meta value. If you have more than one record with the same meta key, you can specify which one to delete by matching this value. It defaults to nothing, which will delete all meta rows with a matching post_id and meta_key.

Example 2-7 demonstrates some of the basic functions for interacting with the wp_commentsmeta table.

Example 2-7. Working with the wp_commentsmeta table
<?php
// get comments - last comment ID
$comments = get_comments( 'number=1' );
foreach ( $comments as $comment ) {
	$comment_id = $comment->comment_ID;

	// add comment meta - meta for view date & IP address
	$viewed = array( date( "m.d.y" ), $_SERVER["REMOTE_ADDR"] );
	$comment_meta_id = add_comment_meta( $comment_id, 'bwawwp_view_date',
        $viewed, true );
	echo 'comment meta id: ' . $comment_meta_id;

	// update comment meta - change date format to format like
	// October 23, 2020, 12:00 am instead of 10.23.20
	$viewed = array( date( "F j, Y, g:i a" ), $_SERVER["REMOTE_ADDR"] );
	update_comment_meta( $comment_id, 'bwawwp_view_date', $viewed );

	// get comment meta - all keys
	$comment_meta = get_comment_meta( $comment_id );
	echo '<pre>';
	print_r( $comment_meta );
	echo '</pre>';

	// delete comment meta
	delete_comment_meta( $comment_id, 'bwawwp_view_date' );
}

/*
The output from the above example should look something like this:
comment meta id: 16
Array
(
    [bwawwp_view_date] => Array
        (
            [0] => a:2:{i:0;s:24:"August 11, 2018, 4:16 pm";i:1;s:9:"127.0.0.1";}
        )

)
*/
?>

wp_terms

The wp_terms table stores each category name or term name that you create. Each record is tied to its taxonomy in the wp_term_taxonomy table by the term_id. So you’re familiar with post categories and tags? Well, each category or tag is stored in this table, and technically they are both taxonomies. Every term that is stored in the name column is a taxonomy term. We will be covering taxonomies in much more detail in Chapter 5, so if you don’t fully grasp what a taxonomy is, you will soon. Table 2-8 shows the database structure for the wp_terms table.

Table 2-8. Database schema for wp_terms table
Column Type Collation Null Default Extra

term_id

bigint(20)

No

None

AUTO_INCREMENT

name

varchar(200)

No

slug

varchar(200)

utf8_general_ci

No

term_group

bigint(10)

No

0

Functions Found in /wp-includes/taxonomy.php

The following functions are found in /wp-includes/taxonomy.php.

get_terms( $taxonomies, $args = '' )

This function gets the terms of a specific taxonomy or an array of taxonomies:

$taxonomies

A required string or array of a taxonomy or list of taxonomies.

$args

An optional string or array of arguments. Available arguments are:

orderby

Default is name. Can be name, count, term_group, slug, or nothing, which will use term_id. Passing a custom value other than these will cause the terms to be ordered on that custom value.

order

ASC or DESC. The default is ASC.

hide_empty

The default value is true, which will only return terms that are attached to a post. If set to false, you can return all terms regardless of whether they are being used by a post or not.

exclude

An array or comma-separated or space-delimited string of term IDs to exclude from the query results. If include is being used, exclude will be ignored.

exclude_tree

An array or comma-separated or space-delimited string of term IDs to exclude from the query results, including any child terms. If include is being used, exclude_tree will be ignored.

include

An array or comma-separated or space-delimited string of term IDs to include in the query results.

number

The number of terms for the query to return. The default is all.

offset

The number by which to offset the terms query.

fields

You can specify if you want to return term IDs or names. The default is all, which returns an array of term objects.

slug

A string that will return any terms that have a matching slug.

hierarchical

Includes all child terms if they are attached to posts. The default is true, so to not return terms hierarchically, set this value to false.

search

A string that will return any terms whose names match the value provided. The search is case-insensitive.

name_like

A string that will return any terms whose names begin with the value provided. Like search, this string is case-insensitive.

pad_counts

If set to true, the query results will include the count of each term’s children.

get

If set to all, returns terms regardless of ancestry or whether the terms are empty.

child_of

When set to a term ID, the query results will contain all descendants of the provided term ID. The default is 0, which returns everything.

parent

When set to a term ID, the query results will contain the direct children of the provided term ID. The default is an empty string.

cache_domain

Enables a unique cache key to be produced when this query is stored in object cache.

get_term( $term, $taxonomy, $output = OBJECT, $filter = ‘raw’ )

This function gets all term data for any given term:

$term

A required integer or object of the term to return.

$taxonomy

A required string of the taxonomy of the term to return.

$output

An optional string of the output format. The default value is OBJECT, and the other values can be ARRAY_A (associative array) or ARRAY_N (numeric array).

$filter

An optional string of how the context should be sanitized on output. The default value is raw.

wp_insert_term( $term, $taxonomy, $args = array() )

This function adds a new term to the database:

$term

A required string of the term to add or update.

$taxonomy

A required string of the taxonomy to which the term will be added.

$args

An optional array or string of term arguments to be inserted/updated. Available arguments are as follows:

alias_of

An optional string of the slug of which the term will be an alias.

description

An optional string that describes the term.

parent

An optional integer of the parent term ID of which this term will be a child.

slug

An optional string of the slug of the term.

wp_update_term( $term_id, $taxonomy, $args = array() )

This function updates an existing term in the database:

$term_id

A required integer of the term ID of the term you want to update.

$taxonomy

A required string of the taxonomy with which the term is associated.

$args

An optional array or string of term arguments to be updated. These are the same arguments used in wp_insert_term().

wp_delete_term( $term, $taxonomy, $args = array() )

This function deletes a term from the database. If the term is a parent of other terms, the children will be updated to that term’s parent:

$term

A required integer of the term ID of the term you want to delete.

$taxonomy

A required string of the taxonomy with which the term is associated.

$args

An optional array to overwrite term field values.

wp_termmeta

Since WordPress 4.4, metadata can be stored for terms. The Simple Taxonomy Ordering plugin by YIKES, Inc. uses term meta to allow you to reorder how your categories and other taxonomies show up in lists and widgets.

Table 2-9. Database schema for wp_termmeta table
Column Type Collation Null Default Extra

meta_id

bigint(20)

No

None

AUTO_INCREMENT

term_id

bigint(20)

No

0

meta_key

varchar(255)

utf8_general_ci

Yes

NULL

meta_value

longtext

utf8_general_ci

Yes

NULL

The functions that follow work similarly to the variants for user meta, post meta, and comment meta.

get_term_meta( $term_id, $key = '', $single = false )

This function gets a term’s meta value for a specified key:

$term_id

A required integer of a term ID.

$key

An optional string of the meta key of the value you would like to return. If blank, all metadata for the given term will be returned.

$single

A Boolean for whether to return a single value. The default is false; thus, the value will be returned as an array.

There can be more than one meta key for the same term ID with different values. If you set $single to true, you will get the first key’s value; if you set it to false, you will get an array of the values of each record with the same key.

update_term_meta( $term_id, $meta_key, $meta_value, $prev_value = '' )

This function updates term metadata but will also insert metadata if the passed-in key doesn’t already exist:

$term_id

A required integer of a term ID.

$meta_key

A required string of the meta key name for the meta value you would like to store. If this meta key already exists, it will update the current row’s meta value; if not, it will insert a new row.

$meta_value

A required mixed value of an integer, string, array, or object. Arrays and objects will automatically be serialized.

$prev_value

An optional mixed value of the current metadata value. If a match is found, it will replace the previous/current value with the new value you specified. If left blank, the new meta value will replace the first instance of the matching key. If you have five rows of metadata with the same key and you don’t specify which row to update with this value, it will update the first row and remove the other four.

Note

This function relies on the update_metadata() function located in /wp-includes/meta.php. Check it out!

add_term_meta( $term_id, $meta_key, $meta_value, $unique = false )

This function inserts brand-new term meta into the wp_termmeta table. Again, it is preferred to use update_term_meta() to insert new rows as well as update them. If you want to ensure that a given meta key is used only once per term, you should use this function and set the $unique parameter to true:

$term_id

A required integer of a term ID.

$meta_key

A required string of the meta key name for the meta value you would like to store.

$meta_value

A required mixed value of an integer, string, array, or object.

$unique

An optional Boolean that, when set to true, will make sure the meta key can be added only once for a given ID.

delete_term_meta( $term_id, $meta_key, $meta_value = '' )

This function deletes term metadata for a provided term ID and matching key. You can also specify a matching meta value if you want to delete only that value and not other metadata rows with the same meta key:

$term_id

A required integer of a term ID.

$meta_key

A required string of the meta key name for the meta value you would like to delete.

$meta_value

An optional mixed value of the meta value. If you have more than one record with the same meta key, you can specify which one to delete by matching the meta value. It defaults to nothing, which will delete all meta rows with a matching term_id and meta_key.

wp_term_taxonomy

The wp_term_taxonomy table stores each taxonomy type you are using. WordPress has two taxonomy types built in, category and post_tag, but you can also register your own taxonomies. When a new term is added in the wp_terms table, it is associated with its taxonomy in this table, along with that taxonomy term ID, description, parent, and count. Table 2-10 shows the structure for the wp_term_taxonomy table.

Table 2-10. Database schema for wp_term_taxonomy table
Column Type Collation Null Default Extra

term_taxonomy_id

bigint(20)

No

None

AUTO_INCREMENT

term_id

bigint(20)

No

0

taxonomy

varchar(32)

utf8_general_ci

No

description

longtext

utf8_general_ci

No

None

parent

bigint(20)

No

0

count

bigint(20)

No

0

/wp-includes/taxonomy.php

You can find the following functions in /wp-includes/taxonomy.php.

get_taxonomies( $args = array(), $output = ‘names', $operator = ‘and’ )

This function returns a list of registered taxonomy objects or a list of taxonomy names:

$args

An optional array of arguments to query what taxonomy objects are returned. There are a lot, and we cover all of them in Chapter 5.

$output

An optional string of either names or objects. The default is names, which returns a list of taxonomy names.

$operator

An optional string of either and or or. The default is and, meaning all the arguments passed in must match. If set to or, any arguments passed in can match.

get_taxonomy( $taxonomy )

This function will first check that the parameter string given is a taxonomy object; if it is, it will return it:

$taxonomy

A required string of the name of the taxonomy object to return.

register_taxonomy( $taxonomy, $object_type, $args = array() )

This function creates or updates a taxonomy object. Registering custom taxonomies can really extend WordPress because you can categorize your posts any way you see fit. We’ll go over registering taxonomies in much more detail in Chapter 5:

$taxonomy

A required string of the name of the taxonomy.

$object_type

A required array or string of the object types (post types like post and page) to which this taxonomy will be tied.

$args

An optional array or string of arguments. There are a lot of these, and we cover all of them in Chapter 5.

wp_term_relationships

The wp_term_relationships table relates a taxonomy term to a post. Every time you assign a category or tag to a post, it’s being linked to that post in this table. Table 2-11 shows the structure for the wp_term_relationships table.

Table 2-11. Database schema for wp_term_relationships table
Column Type Collation Null Default Extra

object_id

bigint(20)

No

0

term_taxonomy_id

bigint(20)

No

0

term_order

int(11)

No

0

get_object_taxonomies( $object, $output = ‘names’ )

This function returns all taxonomies associated with a post type or post object:

$object

A required array, string, or object of the name(s) of the post type(s) or post object(s).

$output

An optional string of either names or objects. The default is names, which returns a list of taxonomy names.

wp_get_object_terms( $object_ids, $taxonomies, $args = array() )

This function returns terms associated with a supplied post object ID or IDs and a supplied taxonomy:

$object_ids

A required string or array of object IDs for the object terms you would like to return. Passing in a post ID would return terms associated with that post ID.

$taxonomies

A required string or array of the taxonomy names from which you want to return terms. Passing in the taxonomy post_tag would return terms of the post_tag taxonomy.

$args

An optional array or string of arguments that change how the data is returned. Here are the arguments you can change:

orderby

Defaults to name; also accepts count, slug, term_group, term_order, and none.

order

Defaults to ASC; also accepts DESC.

fields

Defaults to all; also accepts ids, names, slugs, and all_with_object_id. This argument dictates what values are returned.

wp_set_object_terms( $object_id, $terms, $taxonomy, $append = false )

This function adds taxonomy terms to a provided object ID and taxonomy. It has the ability to overwrite all terms or to append new terms to existing terms. If a term passed into this function doesn’t already exist, it will be created and then related to the provided object ID and taxonomy:

$object_id

A required integer of the object ID (post ID) to which to relate your terms.

$terms

A required array, integer, or string of the terms you want to add to an object (post).

$taxonomy

A required array or string of the taxonomy or taxonomies to which you want to relate your terms.

$append

An optional Boolean that defaults to false and will replace any existing terms related to an object ID with the new terms you provided. If it is set to true, your new terms will be appended to the existing terms.

Note

There was once discussion of a future WordPress release to remove the wp_terms table. The name and slug columns of wp_terms would be moved into the wp_terms_taxonomy table, and a MySQL view created called wp_terms, that could be queried against, preserving backward compatibility for custom queries. This update was shelved, but it would be nice to clean up some tables around terms and taxonomies.

Hooks: Actions and Filters

WordPress developers hook for a living! Hooks are great, and they make adding functionality into WordPress plugins and themes simple and easy.

There are two types of hooks—actions and filters—and they are two of the most powerful tools in WordPress. We spend a lot of time working with actions and filters. Understanding this section is important to your growth as a WordPress developer.

Actions

Where an action hook (technically a do_action() function) exists in code running on WordPress, you can insert your code by calling the add_action() function and passing in the action hook name and custom function with the code you want to run:

do_action( $tag, $arg );

Here are the available arguments:

$tag

The name of the action hook being executed.

$arg

One or more additional arguments that are passed through to the function called from the add_action() function referencing this do_action() function. Say what? Keep reading…

You can create your own hook in a theme or plugin by adding your own do_action() functions. However, most of the time you will be using established hooks in the WordPress core or other plugins. For example, suppose you wanted to check whether a user was logged in when WordPress first loads up but before any output is displayed to the browser. You can use the init hook:

<?php
add_action( 'init', 'my_user_check' );

function my_user_check() {
	if ( is_user_logged_in() ) {
		// do something because a user is logged in
	}
}
?>

So what just happened? In the core of WordPress, there is an action hook, do_action(init), and we are calling a function called my_user_check() from the add_action() function. At whatever point in time the code is being executed, when it gets to the init action hook, it will run our custom my_user_check() function to do whatever we want before continuing on.

Note

Check out WordPress’s reference page for a list of the most used WordPress hooks.

Filters

Filters are kind of like action hooks in the sense that you can tap into them wherever they exist in WordPress. However, instead of inserting your own code where the hook or do_action() exists, you are filtering the returned value of existing functions that are using the apply_filters() function in WordPress core, plugins, and/or themes. In other words, by utilizing filters, you can hijack content before it is inserted into the database or before it is displayed to the browser as HTML:

apply_filters( $tag, $value, $var );
$tag

The name of the filter hook.

$value

The value on which the filter can be applied.

$var

Any additional variables, such as a string or an array, passed into the filter function.

If you search the core WordPress files for apply_filters() you will find that this function is called all over the place, and like action hooks, it can also be added to and called from any theme or plugin. Anywhere in code running on your WordPress site that you see the apply_filters() function being called, you can filter the value being returned by that function. For our example, we are going to filter the title of all posts before they are displayed to the browser. We can hook into any existing filters using the add_filter() function:

add_filter( $tag, $function, $priority, $accepted_args );
$tag

The name of the filter hook you want to filter. This should match the $tag parameter of the apply_filters() function call for which you want to filter the results.

$function

The name of the custom function used to actually filter the results.

$priority

This number sets the priority in which your add_filter() function will run compared to other places in the code that might be referencing the same filter hook tag. By default, this value is 10.

$accepted_args

You can set the number of parameters that your custom function that handles the filtering can accept. The default is 1, which is the $value parameter of the apply_filters() function.

OK, so how would real code for this look? Let’s start by adding a filter to alter the title of any post returned to the browser. We know of a filter hook for the_title that looks like this:

apply_filters( 'the_title', $title, $id );

$title is the title of the post, and $id is the ID of the post:

<?php
add_filter( 'the_title', 'my_filtered_title', 10, 2 );

function my_filtered_title( $value, $id ) {
	$value = '[' . $value . ']';
	return $value;
}
?>

The preceding code should wrap any post titles in brackets. If your post title was “hello world,” it would now read “[hello world].” Note that we didn’t use the $id in our custom function. If we wanted to, we could have applied the brackets to only specific post IDs.

Note

While add_action() is meant to be used with do_action() hooks, and add_filter() is meant to be used with apply_filters() hooks, the functions work the same way and are interchangeable. For readability, it is still a good idea to use the proper function depending on whether you intend to return a filtered result or just perform some code at a specific time.

Development and Hosting Environments

WordPress needs a web server to run. This section covers the basics of setting up a local and remote environment for your WordPress app.

Working Locally

Before we get into WordPress basics, we suggest that you set up a local development environment to run your WordPress installation. You can run WordPress on your desktop computer or laptop, which will make development more efficient and faster. You can run code locally versus using FTP or deploying code from a code repository to a web server. You can also write and test code without having an internet connection. There’s a productive workday with your laptop and Mother Nature somewhere in your future.

There are a ton of online resources on how to run WordPress locally, so we aren’t going to cover them all in detail, but based on your OS and preferences you will most likely be setting up a MAMP (Mac, Apache, MySQL, PHP), WAMP (Windows, Apache, MySQL, PHP), or LAMP (Linux, Apache, MySQL, PHP) stack. Also check out XAMPP and AMPPS, which are cross-platform stacks.

There are a few local web server tools developed specifically for WordPress. DesktopServer by ServerPress and Local by Flywheel are popular tools that streamline all of the semitedious configuration settings for setting up local WordPress installs via their UI.

Tools like VirtualBox, Vagrant, and Docker are also popular in the WordPress community. These tools are especially good for certain automated testing and deployment schemes. WordPress.org has a good document for installing Varying Vagrant Vagrants (VVV), which is popular among core contributors.

Choosing a Web Host

If you don’t already know what a web host is, you have some Googling to do. In short, a web host is where your website resides, specifically your WordPress directory and database.

We are assuming that most of you reading this already work or have worked with a web-hosting company, or maybe you work for a company that has its own internal web servers. Choosing a good host for your web application is key to ensuring it’s fast, secure, and scalable. There are lots of web hosting companies out there, and pretty much all of them will be able to host WordPress, but not all of them are optimized specifically for WordPress.

A “Managed” WordPress hosting company would be the best choice for a high-scale WordPress-powered web application because its focus is on providing optimized WordPress hosting environments. For large-scale websites, a lot of work must go into the caching of the data because of the way the WordPress database is structured with storing metadata. If you use WordPress as a large CMS with lots of posts with lots of post meta on an insufficiently powerful server, it will start to buckle and eat up server resources. Hosting companies with a focus on optimized WordPress have built-in caching systems that help optimize your content delivery.

You can always use caching plugins if your host doesn’t do all the caching for you (Chapter 14 covers caching and other scaling considerations if you are managing your own environment). Some managed WordPress hosts offer other advanced tools like automatic plugin updates and services liked CDN integration geared toward optimizing your hosted WordPress environment.

Some examples of managed WordPress hosting companies include WP Engine, WordPress VIP, and Pagely. There are many other options for hosting. We maintain an up-to-date list of hosts for all sizes at our website.

Development, Staging, and Production Environments

A typical website project will have three code environments: Development, Staging, and Production. Ideally, all three environments are separate web servers, with separate databases, and separate installations of WordPress.

The Development environment (sometimes referred to as Dev or DEV) is where you do your new coding and maintenance work. Typically, it’s the local environment you set up using the information earlier in this chapter.

The Staging environment (sometimes referred to as Testing or TEST) is where you do your testing. The data on the Staging site should be as close as possible to the Production site. This means that you will sometimes be exporting data from the live site, scrubbing it to remove private user information, and importing it into the Staging site.

The Production environment (sometimes referred to as Live or PRD) is the real website your users visit and interact with.

If you can’t have all three code environments, at the very least you want to have a separate Development and Production environment. You should never update code on a Production website without testing it thoroughly on a Development site.

Ideally you would do all of your development locally and then commit your code to a code repository and deploy it to a Development site that can have multiple developers working on it at the same time. Then, once it’s ready to be thoroughly tested, maybe by your boss or client in an environment that is an exact copy of the Production site, you would deploy your code to the Staging site. Finally, once everything checks out on the Staging site, you deploy your code into Production. Make backups of the Production website before deploying any code in case you need to roll back any updates. And finally, never assume that your code will work without testing it.

Some managed WordPress hosting companies like WP Engine have automatic Staging sites for every WordPress site you have with it, which is a really cool feature.

Note

If you were thinking about FTP when “deploying code” was mentioned earlier, you should up your game and use a source code repository like GitHub.

Extending WordPress

Now you know the fundamentals of how WordPress is set up, how the data is stored, and the basic tools for manipulating that data. You’ve been introduced to action and filter hooks, which are a primary method for extending WordPress.

We cover more of the various built-in functions and methods used to interact with WordPress data throughout the book. Chapter 3 covers the WordPress Plugin API, including some of the key features of WordPress that make extending it easy, powerful, and consistent!

1 …ever, ever, ever…

2 The third parameter for add_option, which was deprecated in 2.3, used to be a "description" string that was stored along with the option in the wp_options table.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.190.207.144