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.