Documente Academic
Documente Profesional
Documente Cultură
| CodePeach
06
AUG WordPress Database Interaction with $wpdb.
There are a number of ways to interact with the database when developing for WordPress. Wherever possible, you should use the many core WP functions for working with
Contents [hide]
database data, for example: get_pages can return an array of pages that meet criteria you specify.
0.1 PHP MySQL Options
However sometimes you may need to deal with the db a little more directly to craft queries that go beyond the scope of the standard core WP functions. Unfortunately we 1 Introducing $wpdb
still see WP plugin or theme developers doing this in ways that are vulnerable to SQL injections, and it only takes one security hole to put your entire site at risk. 2 WP Table Names
3 Prepared Queries with $wpdb
4 SELECT Queries with $wpdb
5 INSERT Queries with $wpdb>insert
5.0.1 Replacing Rows with $wpdb>replace
6 UPDATE Queries with $wpdb>update
7 DELETE Queries with $wpdb>delete
8 Custom SQL Queries with $wpdb
>query
9 Further info
PHP’s newer mysqli_* functions are a vast improvement, with support for prepared statements, multiple statements, transactions, debugging capabilities, and it’s OO (object orientated).
There’s also PDO (PHP Data Objects) – a database abstraction layer, which provides a consistent interface which can be used with a variety of DB drivers (MySQL, MS SQL, Firebird, PostgreSQL and others).
This means your PHP application can be run on a wider variety of server configurations in a consistent manner.
Using any of the above options for database interactions in WordPress would see alot of work from the WordPress core developers gone to waste. Here is a little reference guide to get you on the right track to
deal with db calls the recommended, safest way – using $wpdb.
Introducing $wpdb
The WordPress core features a WordPress Database Access Abstraction Object class called wpdb(), which is based on ezSQL by Justin Vincent.
Unless we’re wanting to deal with another database than the WP database, we don’t need to create a new instance of wpdb() as we can use the instance that is created by the WP core, $wpdb. Conveniently, it
will usually be connected to the site’s db already by the time your plugin or theme code is executed.
Quick example showing use of WP’s $wpdb instance:
1 global $wpdb;
2
3 /* lets retrieve the mysql version number using $wpdb */
4 $dbVersion = $wpdb->db_version();
5 if ($dbVersion) {
6 echo "Running MySQL " . $dbVersion;
7 } else {
8 echo "MySQL version unavailable.";
9 }
WP Table Names
The wpdb() class provides us with the table names of the WordPress database tables. This is useful as WP gives site administrators setting a table name prefix other than the default wp_* (eg the posts table
may be named “wpsite2014_posts” rather than the default “wp_posts”), so WP developers should never hardcode table names into sql queries.
Here’s the list of table names available that we can reference in our code:
PHP
1 $wpdb->posts
2 $wpdb->postmeta
3 $wpdb->comments
http://codepeach.com/wordpress/wordpressdatabaseinteractionwpdb/ 1/5
18/06/2017 WordPress Database Interaction with $wpdb. | CodePeach
4 $wpdb->commentmeta
5 $wpdb->terms
6 $wpdb->term_taxonomy
7 $wpdb->term_relationships
8 $wpdb->users
9 $wpdb->usermeta
10 $wpdb->links
11 $wpdb->options
12
13 /* WP Multisite table names */
14 $wpdb->blogs
15 $wpdb->signups
16 $wpdb->site
17 $wpdb->sitemeta
18 $wpdb->sitecategories
19 $wpdb->registration_log
20 $wpdb->blog_versions
Let’s prepare this query so that we use the proper table name (as the table name itself can vary depending on table prefix!) and sanitize the post_author ID to ensure only an integer is put into the query. We do
this using wpdb::prepare, which also takes care of any escaping of the string to help avoid SQL injections.
1 global $wpdb;
2 $prepared = $wpdb->prepare(
3 "SELECT ID, post_title FROM $wpdb->posts
4 WHERE `post_status` = 'publish'
5 AND `post_type` = 'post'
6 AND `post_author` = %d", 3 );
You can see the $wpdb>prepare method has a 2nd parameter passed above, the value of the post_author ID we wish to search for. The method supports sprintf() like syntax for supplying parameters to go
into the placeholders in a query string. You can have as many placeholders as you like within the query string, just pass additional parameters when calling the method.
The supported placeholder types are:
%d (integer)
%f (float)
%s (string)
Tip: If your query string should have a % symbol within it (eg %LIKE%), you can escape those symbols using %% ×
$wpdb>get_var( ‘query’, column_offset, row_offset );
Retrieves a single value from a query at specified column and row offsets. As an example, lets grab the number (count) of published posts by author ID held in $authID. We will wrap the query string with the
prepare() method to ensure the query is clean:
1 global $wpdb;
2
3 $postCount = $wpdb->get_var( $wpdb->prepare(
4 "SELECT COUNT(*) FROM $wpdb->posts
5 WHERE `post_status` = 'publish'
6 AND `post_type` = 'post'
7 AND `post_author` = %d", $authID
8 ), 0, 0 );
9
10 echo "Author has $postCount published posts.";
$wpdb>get_row(‘query’, output_type, row_offset);
Returns a whole row from a query at the specified offset. Output_type defaults to OBJECT, and row_offset defaults to 0, so these parameters are optional. If you’d rather work with an associative array, set
output_type to the constant ARRAY_A.
As an example, let’s grab the title and post ID of the latest published post with post type held in $postType (eg “post” or “page”) by the author ID held in $authID:
1 global $wpdb;
2
3 $newest = $wpdb->get_row( $wpdb->prepare(
4 "SELECT ID, post_title FROM $wpdb->posts
5 WHERE `post_status` = 'publish'
6 AND `post_type` = %s
7 AND `post_author` = %d
8 ORDER BY post_date DESC", $postType, $authID
9 ), OBJECT, 0 );
10
11 echo "ID $newest->ID : $newest->post_title";
$wpdb>get_results( ‘query’, output_type );
Fetches all results of a query (multiple rows if matched), and returns them as the defined output_type (defaults to OBJECT). If you prefer to work with associative arrays for the rows, you can specify output_type
as ARRAY_K, with the rows returned in a numerically indexed array (eg $results[0][‘column_name’] ). Additionally, the row count of the query will be stored in $wpdb>num_rows.
This example shows using get_results to grab the titles of all published posts by author ID $authID, and we iterate over the results to echo out all found post titles:
1 global $wpdb;
2 $titles = $wpdb->get_results( $wpdb->prepare(
3 "SELECT post_title FROM $wpdb->posts
4 WHERE `post_status` = 'publish'
5 AND `post_type` = 'post'
6 AND `post_author` = %d
7 ORDER BY post_date DESC", $authID
8 ), OBJECT);
9
10 foreach ($titles as $title) {
11 echo $title->post_title . '<br />';
12 }
http://codepeach.com/wordpress/wordpressdatabaseinteractionwpdb/ 2/5
18/06/2017 WordPress Database Interaction with $wpdb. | CodePeach
The wpdb() class has an insert() method for inserting a row into a table:
$wpdb>insert( $table, $data, $format );
$table = table name, such as $wpdb>posts
$data = associative array of unescaped values ( column_name => value, .. )
$format = array of data types for the values in $data, eg: array(‘%s’, ‘%d’). This is optional so if omitted, it will treat each value as type string. Possible values for format types are %s for string, %d for integers, %f
for floats.
The insert() method returns false if it failed to insert the row, but if successful it will store the AUTO_INCREMENT ID of the newly inserted row in $wpdb>insert_id. There is no need to call prepare() method
here, or to escape the values ourselves, as the insert() method does this for us.
Here’s an example in which we will insert a new row into the wp_options table, with the option name “peach_option” and the value set to a string held in $peachValue :
1 global $wpdb;
2 $result = $wpdb->insert(
3 $wpdb->options,
4 array(
5 'option_name' => 'peach_option',
6 'option_value' => $peachValue
7 ),
8 array(
9 '%s',
10 '%s'
11 )
12 );
13 if ($result) {
14 echo 'Inserted row ID#' . $wpdb->insert_id;
15 } else {
16 echo 'Insert failed!';
17 }
$wpdb>replace( $table, $data, $format );
This method shares the same parameters as insert(), and the first item in the $data array should be the index for the row.
The method returns back the sum of the rows deleted and inserted, so 1 if the row didn’t exist previously but was inserted, and 2 or more if there were rows deleted and inserted, and false if a row wasn’t able to
be deleted or inserted.
Here’s our previous insert() example reworked to use replace() instead, so if the option name “peach_option” is already saved, it is deleted first and then our new row inserted, preventing row duplication:
1 global $wpdb;
2 $result = $wpdb->replace(
3 $wpdb->options,
4 array(
5 'option_name' => 'peach_option',
6 'option_value' => $peachValue
7 ),
8 array(
9 '%s',
10 '%s'
11 )
12 );
13 if ($result) {
14 echo 'Saved, row ID# ' . $wpdb->insert_id;
15 } else {
16 echo 'Save failed!';
17 }
$wpdb>update( $table, $data, $where, $format = null, $where_format = null );
$table = name of the table to update
$data = data to update (mapped array column => value (unescaped))
$where = named array of WHERE clauses (in column => value pairs)
$format = array of formats to be mapped to each of the values in $data
$where_format = array of formats to be mapped to each of the values in $where.
Update returns the number of rows affected if successful, or false on error. As an example, let’s update the author ID of all posts belonging to the author ID held in $oldAuthor to the new ID held in $newAuthor:
1 global $wpdb;
2 $result = $wpdb->update(
3 $wpdb->posts,
4 array(
5 'post_author' => $newAuthor // column & new value
6 ),
7 array( 'post_type' => 'post', // where clause(s)
8 'post_author' => $oldAuthor ), // match old author id
9 array(
10 '%d', // update vals format type - post_author = integer
11 ),
12 // where clause(s) format types
13 array( '%d', // post type = string
14 '%s' // post_author = integer
15 )
16 );
17 if ($result) {
18 echo "updated $result row(s).";
19 } else {
20 echo "failed to update!";
21 }
$wpdb>delete( $table, $where, $where_format = null );
$table = table name to delete from
$where = mapped array of where clause(s) to match row(s) for deletion
$where_format = array of value data types for the $where clauses
For an example, let’s delete from the wp_options table, any row(s) with the option_name set to ‘peach_option’:
1 global $wpdb;
2
3 $result = $wpdb->delete(
http://codepeach.com/wordpress/wordpressdatabaseinteractionwpdb/ 3/5
18/06/2017 WordPress Database Interaction with $wpdb. | CodePeach
4 $wpdb->options, // table name
5 array( 'option_name' => 'peach_option' ), // where clause
6 array( '%s' ) // where clause data type (string)
7 );
8
9 if ($result) {
10 echo "deleted $result row(s).";
11 } else {
12 echo "failed to delete!";
13 }
$wpdb>query( $sql );
This method doesn’t run any escaping, so you should call the prepare() method also on the $sql string to take care of any escaping / data sanitizing.
Returns the number of rows affected/selected, and false on error.
For an example, let’s create a new custom table, which is common for plugins to do upon plugin installation. We want to keep our table name in line with the rest of the table naming in the database, so for our
table name we shall get the table name prefix for the site and append “peachy” at the end (eg “wp_peachy”).
The site’s table name prefix is stored in $wpdb>prefix.
1 global $wpdb;
2 $tableName = $wpdb->prefix . 'peachy';
3
4 // prepare sql string
5 $sql = $wpdb->prepare("CREATE TABLE %s (
6 id mediumint(9) NOT NULL AUTO_INCREMENT,
7 name VARCHAR(80) DEFAULT '' NOT NULL,
8 UNIQUE KEY id (id)
9 )", $tableName);
10
11 // run query
12 $result = $wpdb->query($sql);
13
14 // determine success
15 if ($result > 0) {
16 echo "hurrah - table created!";
17 } else {
18 echo "uh oh! failed.";
19 }
Further info
I should note that for the update/replace/delete methods, the data should always be unescaped as those methods will do the escaping for you. So on that note, if you’re using data passed on from $_GET and
$_POST, it may be escaped already so just call stripslashes() on that data to avoid additional slashes going into the database.
You can specify whether wpdb() errors should be echoed to the screen, by calling either of these functions:
1 global $wpdb;
2
3 /* turn on error displaying */
4 $wpdb->show_errors();
5
6 /* turn off error displaying */
7 $wpdb->hide_errors();
Links for additional wpdb() info:
wpdb() reference at WP Codex
WP 3.9 wpdb / mysql changes
WP DB Functions @ WP Engineer
I hope you find this article insightful and help you write more secure scripts for WordPress.
We welcome your feedback below, thanks!
← External Link Favicons in WordPress Free Fonts List for 2014 – Part 1 →
http://codepeach.com/wordpress/wordpressdatabaseinteractionwpdb/ 4/5
18/06/2017 WordPress Database Interaction with $wpdb. | CodePeach
Recommend
⤤ Share Sort by Best
Excellent tutorial
2 △ ▽ • Reply • Share ›
△ ▽ • Reply • Share ›
Thanks for the helpful article! FYI, there is a ($) dollar sign in front of your if statement in the success check code example. Peace.
1 △ ▽ • Reply • Share ›
Glad you found it helpful James, and appreciate the heads up - will fix it now, cheers :)
△ ▽ • Reply • Share ›
△ ▽ • Reply • Share ›
△ ▽ • Reply • Share ›
Great post. I'm not sure ARRAY_K is the good name : it is OBJECT_K or ARRAY_A no ?
△ ▽ • Reply • Share ›
ALSO ON CODEPEACH
Grabicon — g.etfv.co seems to be out of commission, but grabicon.com is also free, lets you Simon Rapin — Hi, if you set the $content_width global variable, the embeds won't be larger than
specify image size, and generates a unique default icon for sites that don't have one. … that.if (!isset($content_width)) { $content_width = 1140; }More infos : …
Fruitful theme by fruitfulcode | Hosted by chilli tech.
http://codepeach.com/wordpress/wordpressdatabaseinteractionwpdb/ 5/5