Wordpress development techniques #1 – Running custom queries using the ‘wpdb’ class

wpdb classIn this first edition of “Wordpress development techniques” I will be talking about one of the most useful classes available for use in wordpress: wpdb.

The wpdb class (WordPress DataBase class) is based on the ezSQL class, and handles database connections and queries.

Why use it? You can make all sorts of custom queries, and pull information from the wordpress database, including posts! Read on for more information on this useful class…

What can I use wpdb for?

The wpdb class can be used for running queries on the wordpress database, giving you access to ALL wordpress tables, including posts and categories.

An example use, and the example we will focus on in this article, is pulling recent posts from the database, for example, on a homepage.


Using wpdb

Where can wpdb be used?

Wpdb can be used in templates and plugins within wordpress, it can also be used in web pages that are not part of wordpress if you include the following files:

1
2
include_once('wp-config.php');
include_once('wp-includes/wp-db.php');

If your using the code from a plugin or template file, these files are already included.

Getting started with wpdb

When using wpdb, it is a good idea to first set its scope to global:

1
global $wpdb;

This will allow you to use the wpdb class in your code. Wpdb automatically handles the database connection, so you can immediately start running queries.

Running query’s

To run a query you can call one of the following functions within wpdb (replacing ‘query’ with your sql code):

  1. $wpdb->query('query'); – Runs any query, used for inserts, updates, deletes etc.
  2. $wpdb->get_var('query',column_offset,row_offset); - Get a single variable
  3. $wpdb->get_row('query', output_type, row_offset); – Get a single row
  4. $wpdb->get_col('query',column_offset); – Get a single column as a dimensional array
  5. $wpdb->get_results('query', output_type); – Get generic results

The returned results’ type can be changed by setting ‘output_type’, this can be:

  1. OBJECT – This is the default output, and returns an object.
  2. ARRAY_A – This returns the results as an associative array.
  3. ARRAY_N – This returns the results as a numbered array.

I tend to only use the ‘object’ type, this is down to personal preference.

Get table names easily

wpdb provides an easy method to get wordpress table names, by using the following variables within queries:

  1. $wpdb->posts – The post table that stores posts and pages
  2. $wpdb->postmeta – The table which stores custom field data
  3. $wpdb->categories – The category table
  4. $wpdb->post2cat – The post2cat table which stores the id’s of posts and categories that are linked
  5. $wpdb->comments – The comments table
  6. $wpdb->users – The table of users and user details
  7. $wpdb->links – Stores links
  8. $wpdb->link2cat – The link2cat table which stores the id’s of links and categories that are linked
  9. $wpdb->options – The table of wordpress options

Keeping data safe for insertion

When inserting data into the database, it shoukd always be escaped to stop people hacking your site, wpdb offers a handy little function for doing this – $wpdb->escape

1
$safe_string = $wpdb->escape($unsafe_string);

The above code runs the escape function on an unsafe string, and puts the result into the $safe_string varible. This can then be inserted into the database using wpdb safely.

Other useful functions

Some other useful functions wpdb has are listed below.

  1. $wpdb->show_errors(); – Echoes mysql errors on the page
  2. $wpdb->hide_errors(); – Hides mysql errors on the page
  3. $wpdb->print_error(); – Prints mysql errors on the page
  4. $wpdb->flush(); – Flushes the result cache

Useful variables

After running a query, some useful variables become available:

  1. $wpdb->num_rows – Count of the number of rows returned by the last query (useful in SELECT queries)
  2. $wpdb->insert_id — ID of the AUTO_INCREMENT value of the last query (useful in INSERT queries)
  3. $wpdb->rows_affected – Count of the number of rows affected by the last query (useful in INSERT, UPDATE and DELETE queries)
  4. $wpdb->last_query – The last query ran
  5. $wpdb->last_results – The results of the last query ran


Recent posts example

So I’ve covered the basics, now lets put wpdb into action. Lets say we have a homepage on a wordpress blog, the template for this page is home.php.

On this page we want to show the latest post, plus a list of recent posts (like the setup here at Blue Anvil).

The normal loop

To show the latest entry, just use the normal wordpress loop, as well as query_posts to limit it to one post.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
        query_posts('showposts=1'); // Return only 1 post
	global $more; $more = 0;      // set $more to 0 in order to only get the first part of the post
?>
 
	<?php if (have_posts()) : ?>
 
		<?php while (have_posts()) : the_post(); ?>
 
			<div class="post" id="post-<?php the_ID(); ?>">
				<h2><a href="<?php the_permalink(); ?>" rel="bookmark" title="Permanent Link to <?php the_title(); ?>"><?php the_title(); ?></a></h2>
				<small><?php the_time('F jS, Y') ?> <!-- by <?php the_author() ?> --></small>
 
				<div class="entry">
					<?php the_content('Read the rest of this entry &raquo;'); ?>
				</div>
 
				<p class="postmetadata">Posted in <?php the_category(', ') ?> | <?php edit_post_link('Edit', '', ' | '); ?>  <?php comments_popup_link('No Comments &#187;', '1 Comment &#187;', '% Comments &#187;'); ?></p>
			</div>
 
		<?php endwhile; ?>
 
		<div class="navigation">
			<div class="alignleft"><?php next_posts_link('&laquo; Previous Entries') ?></div>
			<div class="alignright"><?php previous_posts_link('Next Entries &raquo;') ?></div>
		</div>
 
	<?php else : ?>
 
		<h2 class="center">Not Found</h2>
		<p class="center">Sorry, but you are looking for something that isn't here.</p>
		<?php include (TEMPLATEPATH . "/searchform.php"); ?>
 
	<?php endif; ?>

The recent posts

Now lets use wpdb to get recent posts!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<h2>Recently posted</h2>
    <ul id="recent">
		<?php
			global $wpdb;   // Give wpdb with global scope
 
                        // This query selects all posts that are published, orders them by date, offsets the first post by 1 (so we dont show the main post in               the list) and limits it to 3 (so we only show 3 recent posts)
			$sql = 'SELECT DISTINCT * FROM '.$wpdb->posts.' AS POSTS
                                 WHERE POSTS.post_type="post"
                                 AND POSTS.post_status="publish"
                                 ORDER BY POSTS.post_date DESC
                                 LIMIT 1,3;';
 
			$posts = $wpdb->get_results($sql);  // Run our query, getting results as an object
 
				if (!empty($posts)) { // If the query returned something
					 foreach ($posts as $post) {  // Loop though our results!
 
						$post->post_date = date("F j, Y",strtotime($post->post_date));  // Format the date
 
                                                 // Get excerpt, or make our own from content
						 if (empty($post->post_excerpt)) {
							$post->post_excerpt = explode(" ",strrev(substr(strip_tags($post->post_content), 0, 175)),2);
							$post->post_excerpt = strrev($post->post_excerpt[1]);
							$post->post_excerpt.= " [..]";
						 }
 
                                                // Output the row
						print(
							'<li><a href="'.get_permalink($post->ID).'">
							<strong>'.$post->post_title.' - '.$post->post_date.'</strong><br/>'.$post->post_excerpt.'</a></li>'
						);
					 }
				}
		?>
    </ul>

You will notice in the above example, I got the post data by using $post->, there is another way of doing this which enables you to use the normal wordpress template functions (e.g. the_content();). To allow this, add the following code within the foreach loop:

1
 setup_postdata($post);

You can now use functions like the_content();, the_excerpt(); and so on instead of $post->post_content etc.

More information on wpdb

Next week…

Next week we will be looking at wordpress’ built in RSS feed grabbing features, and create our own delicious RSS feed aggregator. See you then!

Found this post useful? Why not buy me a coffee!

Related Entries

8 Responses to “Wordpress development techniques #1 – Running custom queries using the ‘wpdb’ class”

RSS feed for comments on this post.

  1. Anthony Brewitt says:

    I will definetly be using this as a resource – thanks Mike!

    Comment made on June 22, 2007 at 12:34 pm

  2. Mike Cherim says:

    That’s excellent Mike. Thanks. I can see lots of uses for that. For recent post in particular, I like that and may implement it on a site I’m making. Currently I have this…

    &lt;?php wp_get_archives('type=postbypost&amp;limit=4'); ?&gt;

    …which, with the Run PHP plugin (which is a must have as far as I’m concerned) I can grab listed links to the posts postbypost. Not sure if there’s a description or excerpt parameter to add to it do grab some post content as well.

    The number in the string is the number displayed.

    Comment made on June 23, 2007 at 12:47 am

  3. James Oppenheim says:

    Nice article, can’t wait for the next one. Keep up the good work.

    Comment made on June 23, 2007 at 4:35 am

  4. Mike Jolley says:

    @Mike – I take it you put that inside actual wordpress pages? I prefer making a template for a page, then the user can choose that as the template when they create it.

    @ant and @James – Thanks. Ill get the next one out next week ;)

    Comment made on June 23, 2007 at 8:23 am

  5. Mike Cherim says:

    Yes, that’s what I did in this case, Mike. It is embedded directly in a page.

    Comment made on June 23, 2007 at 2:12 pm

  6. Joseph says:

    Another great post – thanks! Would it be possible to use this technique in conjunction with your secure and accessible contact form to pull an email address stored in a post’s custom field and therefore have the contents of the contact form sent to an email address depending on the post ID. I think something like this is being used here:

    http://geofeat.com/directory/air_water/water_home/water_filter_systems/40616/

    Do you think this would work?

    Cheers, Joe

    Comment made on September 26, 2007 at 9:18 am

  7. Andy Bailey says:

    great post, I have been toying with using the wp database for reads and writes since I started making plugins for wordpress. So far I haven’t needed to use the database but I think my future plans for plugins will definitely use it so thanks for making it so clear on how to use wp-db.php!

    Comment made on November 7, 2007 at 11:57 am

  8. James Gardner says:

    Hey,

    Excellent article, just what I was looking for! Perhaps you could help me with something? I have created my own table and want to create an admin panel which lists it’s contents – can I facilitate something within wpdb to organize my results into pages automatically?

    Comment made on December 2, 2007 at 2:00 pm

The comments are closed.

About this site

Blue Anvil is the online web design journal & portfolio of , a web designer from Norfolk, England. Read More »
ThemeSlice
  • Featured work - More

    • Beefjack
    • Integrity
    • theotaku.com
  • Latest Tweet - More

    • New blog post: MiniCard 1.1.7 Update http://blue-anvil.com/archives/minicard-1-1-7-update/
  • Out of the blue - More

    • MiniCard 1.1.7 Update

      I have just uploaded 1.1.7 of MiniCard here and to the WordPress theme directory. This updates includes:

      • New networks; xing, gowalla, yelp, foursquare, mobileme, google buzz
      • A way to change link text and define multiple links of the same network
      • A way to define your own custom links + icons
      • Improved admin panel

      Hope you like it, and don’t forget you can show your support by purchasing the premium pack from here.

    • Switched: From Shared to VPS

      It’s been about two weeks now since I made the transition from a shared reseller hosting account to a VPS (Virtual Private Server) account – impressions so far, excellent performance but fiddly to configure.

      The reason I wanted to change from shared hosting was the fact the server was always being hacked (even though ALL my scripts were secure), there was frequent downtime, support blamed me for problems every time, and it was slow as hell.

      Those used to a shared hosting environment would probably not know where to start when faced with configuring a VPS. Luckily, a lot of it was pre-configured when I received my account – certainly some of the major security holes were patched. I was not satisfied with those however. As a victim of hacking in the past (previous host swears it was not there fault, something I don’t believe) I took extra care to secure it as a much I could – configuring brute force detection, the firewall, installing mod security (excellent rules for that here: http://www.atomicorp.com/wiki/index.php/Atomic_ModSecurity_Rules) and going though multiple guides (like this one: http://www.webhostingtalk.com/showthread.php?t=468168) with a fine-tooth comb.

      The result? My pages are loading at least 6 times faster, I have had no down time (or at least have not noticed any), and I feel in control and happy. No longer am I at the mercy of shared hosts :)

      If your interested, I chose ServInt as my provider as they offered a great deal, as well as being a managed service (so I’m not on my own if I screw things up). I was tempted by the bells and whistles of Media Temple, but felt the ServInt service was better value.

    • Download Monitor 3.2.2 Maintenance Release

      Download Monitor has received some more love and has been updated. Here’s the change log from the new version:

      • Small bugfix in uploader.php – cat ID
      • Changed stats graph calculation – thanks lggemini
      • Changes to headers in download.php to avoid caching
      • File Browser fixes – $root was clashing with something….
      • exclude_cat works in all sections of download_page now
      • Removed hardcoding of /uploads/
      • Added action to download.php – should be able to use it to stop a download if you want – maybe limiting downloads per day or something? Whatever you want…
      • Made it so if you post new file on ‘edit’ screen, the post date is updated.
      • Fixed the ‘blank meta’ section which blanks out custom field values when nothing is set.
      • Moved ‘allow_url_fopen’ check.
      • Someone said downloads don’t work with spaces in the name. They do! Wasting my time sonny…
      • All work and no play make jolley a dull boy
      • Had to rename capabilities so they work. Apologies if you have to set this up again! Cheers to Mark Dingemanse.
      • {category_ID} custom format tag added. Useful if you want to send someone to its category on the DL page I guess. Also added {category_other} so when no category is set “other” is shown – this is because the download page can show an ‘other’ section if you want it to.
      • You can now manually edit the post date on the edit download screen.

      If you have edited capabilities for download monitor user permissions, you’ll have to again sorry! This is because I named them too long. Also, you should check your forced downloads still work because there was a logic error meaning they may not have been forced after-all…

      Enjoy.

    • Mahousive update to Download Monitor (3.2)

      Today I completed the update for the Wordpress Download Monitor Plugin – many tweaks, fixes, and features added. There were no changes to the database structure so people upgrading should be fine. Here is the list from the change log:

      • {user} tag added for custom formats
      • ‘autop’ option fix
      • Download page buttons applied with CSS so they are easier to customise/translate.
      • Fix for pagination bug after editing a download
      • Category output fix on edit downloads screen
      • Category urls on download page use ID rather than name to prevent errors when cats have the same names.
      • exclude_cat added to download_page shortcode
      • Localised ‘hits’ ‘date’ ‘title’ on download page
      • Option to disable the download logging
      • Read file ‘chunked’ some people found large files were corrupted so this should help (fingers crossed)
      • Added show_tags option to download page – displays x amount of tags on the download page.
      • File Browser root setting and download.php logic/mime types modified thanks to Jim Isaacs (jidd.jimisaacs.com)
      • Interface Improvements
      • Bulk edit categories, custom fields, tags, member only downloads
      • Added roles for download monitor admin – should be able to use with a role manager plugin if you want anyone other than admin to access the admin section e.g. http://wordpress.org/extend/plugins/capsman/
      • Change redirect after add
      • Edit Cat names/parents
      • Dedicated tags and thumbnails fields (they still use meta table though)

      And yes, those category link bugs are fixed at long last, and you can edit category names finally. Phew!