Sunteți pe pagina 1din 5

18/06/2017 WordPress Database Interaction with $wpdb.

 | 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 MySQL Options


The old  mysql_* functions  should never be used – not only is there no prepared statement support meaning you are relied upon to carry out all sanitizations (or risk SQL injection), but these functions are
deprecated in newer versions of PHP.

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/wordpress­database­interaction­wpdb/ 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

Prepared Queries with $wpdb


Let’s look at crafting a simple SELECT query to grab the id’s and titles of published posts by a specific author ID. The raw SQL query to do this may look something like:

1 SELECT ID, post_title FROM `wp_posts`


2    WHERE `post_status` = 'publish'
3    AND `post_type` = 'post'
4    AND `post_author` = 3

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 %% ×

SELECT Queries with $wpdb


The wpdb() class has a number of methods available to use when running SELECT queries. Whenever part of the query is a variable value,  always use the prepare() method we covered above to make sure the
query string is escaped and sanitized for safe usage. Let’s cover some of these methods:

$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:

Wordpress wpdb::get_var() example PHP

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:

wpdb::get_row example PHP

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";

You can see we introduced using an extra placeholder (for the post_type value) in the query string for the  prepare() method, with it’s type defined as a  string (%s).

$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:

wpdb::get_results() example PHP

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 }

INSERT Queries with $wpdb->insert

http://codepeach.com/wordpress/wordpress­database­interaction­wpdb/ 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 :

wpdb::insert example PHP

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 }

Replacing Rows with $wpdb->replace


What if we want to insert this wp_options row and delete any existing table rows for that option, to prevent row duplications for the option we’re saving? Then we use wpdb::replace().

$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:

wpdb::replace example PHP

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 }

UPDATE Queries with $wpdb->update


Update a row (or multiple rows) that match a where clause, with escaping of values for the placeholders:

$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:

example of wpdb::update() PHP

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 }

DELETE Queries with $wpdb->delete


The delete method is much the same format as update(), and again returns the number of rows affected or false on error.

$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’:

wpdb::delete() example PHP

1 global $wpdb;
2  
3 $result = $wpdb->delete(

http://codepeach.com/wordpress/wordpress­database­interaction­wpdb/ 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 }

Custom SQL Queries with $wpdb->query


Although the above wpdb() methods cover the majority of database interactions you’ll need, there will be times when you want to run queries which aren’t covered above. For example, creating or deleting a
custom table in the WordPress database.

$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.

wpdb::query() example PHP

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:

wpdb error reporting on or off PHP

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!

by Jason   Posted in Wordpress  mysql  August 6, 2014

← External Link Favicons in WordPress Free Fonts List for 2014 – Part 1 →

http://codepeach.com/wordpress/wordpress­database­interaction­wpdb/ 4/5
18/06/2017 WordPress Database Interaction with $wpdb. | CodePeach

7 Comments CodePeach  Sébastien Méric

 Recommend
⤤ Share Sort by Best

Join the discussion…

Raghu Chintakindi • 3 years ago −

Excellent tutorial

2 △ ▽ • Reply • Share ›

CodePeach.com Mod > Raghu Chintakindi • 3 years ago −

Thanks Raghu, glad you found it useful :)

△ ▽ • Reply • Share ›

James Huckabone • 3 years ago −

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 ›

CodePeach.com Mod > James Huckabone • 3 years ago −

Glad you found it helpful James, and appreciate the heads up - will fix it now, cheers :)

△ ▽ • Reply • Share ›

Maximus McCullough • 16 days ago −

A Jolly Good Tutorial! :-)

△ ▽ • Reply • Share ›

Luke Cavanagh • a month ago −

Thanks for sharing.

△ ▽ • Reply • Share ›

Guillaume Lebret • 3 months ago −

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

External Link Favicons in WordPress Useful WordPress Code Snippets vol.1

1 comment • 3 years ago• 2 comments • 3 years ago•

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 : …

✉ Subscribe d Add Disqus to your siteAdd DisqusAdd 🔒 Privacy

Fruitful theme by fruitfulcode | Hosted by chilli tech.

http://codepeach.com/wordpress/wordpress­database­interaction­wpdb/ 5/5

S-ar putea să vă placă și