WordPress Web Application Development
上QQ阅读APP看书,第一时间看更新

Querying the database

As with most frameworks, WordPress provides a built-in interface for interacting with the database. Most of the database operations will be handled by the wpdb class located inside the wp-includes directory. The wpdb class will be available inside your plugins and themes as a global variable and provides access to all the tables inside the WordPress database including custom tables.

Note

Using the wpdb class for CRUD operations is straightforward with its built-in methods. The complete guide for using the wpdb class can be found at http://codex.wordpress.org/Class_Reference/wpdb.

Querying the existing tables

WordPress provides well-optimized built-in methods for accessing the existing database tables. Therefore, accessing these tables becomes straightforward. Let's see how basic CRUD (Create, Read, Update, and Delete) operations are executed on existing tables.

Inserting records

All the existing tables contain a prebuilt insert method for creating new records. The following list illustrates a few of the built-in insert functions:

  • wp_insert_post: This function creates a new post or page in the wp_posts table
  • add_option: This function creates a new option on the wp_options table, if it doesn't already exist
  • wp_insert_comment: This function creates a new comment in the wp_comments table
Updating records

All the existing tables contain a prebuilt update method for updating existing records. The following list illustrates a few of the built-in update functions:

  • update_post_meta: This function creates or updates additional details about posts in the wp_postmeta table
  • wp_update_term: This function updates the existing terms in the wp_terms table
  • update_user_meta: This function updates the user's meta details in the wp_usermeta table based on the user ID
Deleting records

Similar methods are available for deleting records in each of the existing tables.

Selecting records

As usual, there is a set of built-in functions for selecting records from the existing tables. The following list contains few of the data selecting functions:

  • get_posts: This function retrieves the posts as an array from the wp_posts table based on the passed arguments. Also, we can use the WP_Query class with the necessary arguments to get the post list from the OOP method.
  • get_option: This function retrieves the option value of the given key from the wp_options table.
  • get_users: This function retrieves the list of users as an array from the wp_user table.

Most of the database operations on existing tables can be executed using these built-in functions. So, use of the $wpdb class is not necessary in most occasions unless queries become complex and hard to handle using direct functions.

Querying the custom tables

Basically, there are no built-in methods for accessing custom tables using direct functions. So, it's a must to use the wpdb class for handling custom tables. Let's take a look at some of the functions provided by the wpdb class:

  • $wpdb->get_results( "select query" ): This function can be used to select a set of records from any database table.
  • $wpdb->query('query'): This function can be used to execute any custom query. This is typically used for update and delete statements instead of select statements as it only provides the affected rows' count as the result.
  • $wpdb->get_row('query'): This function can be used to retrieve a single row from the database as an object, an associative array, or as a numerically indexed array.

The complete list of the wpdb class functions can be accessed at http://codex.wordpress.org/Class_Reference/wpdb. When executing these functions, we have to make sure that we include the necessary filtering and validations as these are not built to directly work with the existing tables. For example, consider the following query for proper usage of these functions with the necessary filtering:

$wpdb->query(
  $wpdb->prepare("SELECT FROM $wpdb->postmetaWHERE post_id = %d AND meta_key = %s",1, 'book_title'
  )
);

Here, we are filtering the user input values through the prepare function for illegal operations and illegal characters. Similarly, you have to use functions such as escape and escape_by_ref for securing direct SQL queries.

Data validation is an important aspect of keeping the consistency of the database. WordPress offers the prepare function for formatting the SQL queries from possible threats. Usually, developers use the prepare function with direct queries including variables instead of using placeholders and value parameters. It's a must to use placeholders and value parameters to get the intended outcome of the prepare function. Therefore, WordPress Version 3.5 and onwards enforce a minimum of two arguments to prevent developers from misusing the prepare function.

Working with posts

WordPress posts act as the main module in web application development as well as content management systems. Therefore, WordPress comes with a separate class named WP_Query for interacting with the posts and pages. You can look into more details about the use of WP_Query at http://codex.wordpress.org/Class_Reference/WP_Query.

Up until now, we had a look at procedural database access functions using global objects. Web application developers are much more familiar with object-oriented coding. The WP_Query class is a good choice for such developers in querying the database. Let's find out the default usage of WP_Query using the following code:

$args = array(
  'post_type' => 'projects',
  'meta_query' => array(
    array(
    'language' => '',
    'value' => 'PHP'
    )
  )
);

$query = new WP_Query($args);

First, we need to add all the filtering conditions to an array. The WP_Query class allows us to include conditions on multiple tables, such as categories, tags, and postmeta. This technique allows us to create highly complex queries without worrying about the SQL code. The advantage of WP_Query comes with its ability to create sub classes to cater to project-specific requirements. In the next section, we are going learn how to extend the WP_Query class to create custom database access interfaces.

Extending WP_Query for applications

The default WP_Query class works similarly for all types of custom post types. In web applications, we can have different custom post types with different meanings. For example, developers can create services inside our portfolio application. Each service will have a price and process associated with it. There is no point retrieving these services without those additional details. Now, let's look at the default way of retrieving services with WP_Query using the following code:

$args = array(
  'post_type' => 'services',
  'meta_query' => array(
    array(
    'key' => 'price'
    ),
    array(
      'key' => 'process'
    )
  )
);

$query = new WP_Query( $args );

This query works perfectly in retrieving services from the database. However, each time we have to pass the price and process keys in order to join them while retrieving services. Since this is a services-specific requirement, we can create a custom class to extend WP_Query and avoid repetitive argument passing as it's common to all the services-related queries. Let's implement the extended WP_Query class as follows:

class WPWA_Services_Query extends WP_Query {

  function __construct( $args = array() ) {

  $args = wp_parse_args( $args, array(
    'post_type' => 'services',
    'meta_query' => array(
      array(
        'key' => 'price'
      ),
      array(
        'key' => 'process'
      )
    )
  ) );
  parent::__construct( $args );
  }
}

Now, all the common conditions are abstracted inside the WPWA_Services_Query class. So, we don't have to pass the conditions every time we want services. The preceding example illustrates the basic form of object inheritance. Additionally, we can use post filters to combine custom tables with services. Now, we can access services using the following code without passing any arguments:

$query = new WPWA_Services_Query();

The WP_Query class is going to play a vital part in our portfolio application development. In the upcoming chapters, we are going to explore how it can be extended in several ways using advanced post filters provided by WordPress. Until then, you can check out the available post filters at http://codex.wordpress.org/Plugin_API/Filter_Reference#WP_Query_Filters.