And 0 == 1

Sometimes when you are working, you find little things that should be easy to debug, but aren’t. Today I was in that situation twice. The first one because I overlooked the fact that in wordpress, when you want to use the tax_query variable in WP_Query, you need to pass it as an array of arrays. WP_Query kept ignoring my tax_query because instead of this:


$args = array(
  'post_type' => 'tips',
  'posts_per_page' => 3,
  'tax_query' => array(
    array(
      'taxonomy' => 'tips_type',
      'field' => 'id',
      'terms' => $term_id
    )
  )
);

I had this:


$args = array(
  'post_type' => 'tips',
  'posts_per_page' => 3,
  'tax_query' => array(
    'taxonomy' => 'tips_type',
    'field' => 'id',
    'terms' => $term_id
  )
);

But that is not what I wanted to show you. What I want to show you is a bit more interesting. I was writing a small ajax “interface”, which is a fancy way of saying that I was writing a wordpress action hook that would check if the current page being requested had a certain get parameter that would indicate that ajax was being performed. If it was, then a switch would decide what function to call. I was working on something related to the code above.

I have a custom post type named tips, and I wanted to load the next 3 tips in the list. As you can see, I also have a custom taxonomy called tips_type. The problem I run into was that I was getting no tips back, even though I knew I had more tips. A little inspecting revealed the problem.

Upon inspecting the query that went out to the DB, I noticed that there was an AND 0 == 1, which sure enough was the cause of the problem, but it was not the root. To find the root, I needed to dig a bit into wordpress core files.

I started by finding out where that AND 0 == 1 was coming from. I opened up wp-includes/query.php, and started following the $where variable in the get_posts function. How did I find out what to look for? Well, I just did a search for WHERE, in that file, since the part of the query where the 0 == 1 was looked like this: WHERE 1 == 1 AND 0 == 1.

By following the $where variable, I was able to find out that the AND 0 == 1 was added at the point where the sql for the tax_query is retrieved. The relevant lines in the file look like this:


$clauses = $this->tax_query->get_sql($pwdb->posts, 'ID');

$join .= $clauses['join'];
$where .= $clauses['where'];

So I decided to see what was going on inside that get_sql. First I needed to find out where the code for the tax_query object was. For that I just did a quick n’ dirty print_r($this->tax_query); That tells me what class the object is an instance of. Then I searched on the wordpress codex for that class, and got this page http://phpdoc.wordpress.org/trunk/WordPress/Taxonomy/WP_Tax_Query.html that surely tells me where the class definition is.

Next, I loaded the file, and started inspecting the get_sql method. We are getting closer to the root of the problem now, but we are not quite there yet. I see that somewhere in the first few lines of the method, there is a check to see if the $query variable is an error, so I decided to check if that is true or false. It turns out it is true. I decide to do a quick n’ dirty print_r($query);, and find out that the taxonomy does not exists. This right away tells me what is going on. I’m trying to query the taxonomy before it is even registered.

I knew what was going on. I was loading my ajax interface file before the file that defines the custom taxonomy. That is the root of the problem. A line of code that was put too early in the functions.php file.

I feel like if wordpress had a better way to deal with errors where a taxonomy is not defined, I could have avoided a lot of trouble. I don’t blame wordpress, though, it was my own mistake that caused the error.

The way wordpress deals with undefined taxonomies, is by adding an AND 0 == 1 to the WHERE clause of the sql query.This effectively prevents any posts from being selected, since 0 will never be equal to 1.

Advertisements