I've been working on a Drupal module that generates a search form and presents the results below the form. However, I ran into a strange issue where the database query returned 3 records, and yet, the pager was displaying 9 pagination links.
The code that builds and handles the query looks like this:
<?php
$query = 'select
n.nid,
n.title,
DATE_FORMAT(FROM_UNIXTIME(n.created), \'%c/%e/%Y\') as created,
c.field_product_price_value as price,
d.name,
t.tid
from
{node} n
left join {node_revisions} r on r.vid = n.vid
left join {content_type_galleria_product} c on c.nid = n.nid
left join {term_node} t on t.nid = n.nid
left join {term_data} d on d.tid = t.tid ';
$groupby = ' group by n.nid';
$clauses = array();
$clauses[] = 'n.type = \'galleria_product\'';
foreach($form_values as $key => $value)
{
if(($key) && ($value != ''))
{
switch($key)
{
case 'name':
$clauses[] = 'n.title like \'%%'.db_escape_string($value).'%%\'';
break;
case 'price_range':
$clauses[] = 'c.field_product_price_value <= '.db_escape_string($value);
break;
case 'category':
$clauses[] = 't.tid = '.db_escape_string($value);
break;
case 'created':
switch($value)
{
case 'today':
$clauses[] = 'DATE(FROM_UNIXTIME(n.created)) = CURDATE()';
break;
case 'current_week':
$clauses[] = 'WEEK(FROM_UNIXTIME(n.created)) = WEEK(NOW())';
break;
case 'current_month':
$clauses[] = 'MONTH(FROM_UNIXTIME(n.created)) = MONTH(NOW())';
break;
case 'current_year':
$clauses[] = 'YEAR(FROM_UNIXTIME(n.created)) = YEAR(NOW())';
break;
}
break;
default:
break;
}
}
}
$limit = 30;
$header = array(
array('data' => t('Name'), 'field' => 'n.title', 'sort' => 'asc'),
array('data' => t('Rating')),
array('data' => t('Price'), 'field' => 'c.field_product_price_value'),
array('data' => t('Category'), 'field' => 'd.name'),
array('data' => t('Created'), 'field' => 'n.created')
);
$query .= (count($clauses) ? 'WHERE ' . implode(' AND ', $clauses) : '');
$tablesort = tablesort_sql($header);
$result = pager_query($query.$groupby.$tablesort, $limit, 0);
$rows = array();
// Retrieve all the data found by the query
while($data = db_fetch_array($result))
{
$current_avg = votingapi_get_voting_results('node', $data['nid'], 'percent', 'vote', 'average');
$stars = variable_get('fivestar_stars_'. (!isset($node) ? 'default' : $node->type), 5);
$rows[] = array(
l($data['title'], 'node/'.$data['nid']),
theme('fivestar_static', $current_avg[count($current_avg)-1]->value, $stars),
'$'.$data['price'],
l($data['name'], 'taxonomy/term/'.$data['tid']),
$data['created'],
);
}
if(empty($rows))
{
$rows[] = array(array('data' => t('Your search failed to find any products.'), 'colspan' => 3));
}
$output = theme('table', $header, $rows);
$output .= theme('pager', null, $limit);
?>
After banging my head against the wall for a few hours, I came across a post by Kris Buytaert which explained why I was seeing this problem.
To summarize, the code that produces the pagination links is in pager.inc. Within this code is this bit:
<?php
$count_query = preg_replace(array('/SELECT.*?FROM /As', '/ORDER BY .*/'), array('SELECT COUNT(*) FROM ', ''),$query);
?>
You'll note that the pattern matching is case insensitive. As my query was written all in lowercase, the pagination code was not matching anything. All I had to do was rewrite the query such that the MySQL keywords were in uppercase.
A bug, to be sure, considering that the SQL Standard does not call for specific case. As pager.inc is part of the Drupal core, hopefully it will get patched and fixed soon.
[tags]Drupal, module, pager, query[/tags]
Recent comments
18 hours 31 min ago
1 week 6 days ago
1 week 6 days ago
1 week 6 days ago
1 week 6 days ago
1 week 6 days ago
2 weeks 1 day ago
4 weeks 1 day ago
10 weeks 3 days ago
16 weeks 6 days ago