I have two disjointed sets of product filters, $special_filters
and $other_filters
. I'm trying to retrieve the products from the database which match any of the filters in $special_filters
AND any of the filters in $other_filters
. For example, if $special_filters = {'New'}
and $other_filters = {'Brakes', 'Tires'}
then I want to get all new brakes and all new tires, as opposed to all new parts, all brakes, and all tires. Here's what I've gotten to work in phpMyAdmin (here the product_filters
table is a 2-column table relating product_id
and filter_id
:
SELECT q.product_id FROM (
SELECT product_id FROM `<prefix>_j2store_product_filters`
WHERE filter_id = 'tag1'
) AS q
INNER JOIN `<prefix>_j2store_product_filters` AS t ON q.product_id = t.product_id
WHERE filter_id IN ('tag2', 'tag3')
This successfully finds all products that have tag1
, and either tag2
or tag3
. However my translation into Joomla doesn't seem to work.
I'm modifying J2Store's code in administrator/components/com_j2store/models/products.php
, near the end of the _sfBuildWhereQuery
function, which is setting up a JDatabase query object to fetch a list of products. At this point in the code there is a $filter_ids
array which contains all of the active filters and is the union of my two filter arrays, and I need to add an appropriate "WHERE" clause to the current query object. I've basically just tried translating my sql code into JDatabase. Here's my attempt:
$other_ids = array_diff($filter_ids, $special_filters);
if (empty($special_filters) || empty($other_ids)) {
// This is the usual case for the 'OR' operator.
$query->where ( '#__j2store_product_filters.filter_id IN ('
. implode ( ',', $filter_ids ) . ')' );
} else {
// Make sub-sub-query to filter with special filters
$subSubQuery = $db->getQuery(True);
$subSubQuery
->select($db->quoteName('product_id'))
->from($db->quoteName('#__j2store_product_filters'))
->where($db->quoteName('filter_id')
. ' IN (' . implode(',', $special_filters) . ')');
// Filter the result with the other filters in another subquery
$subQuery = $db->getQuery(True);
$subQuery
->select($db->quoteName('s.product_id'))
->from($subSubQuery, 's')
->join('INNER',
$db->quoteName('#__j2store_product_filters', 'f')
. ' ON (' . $db->quoteName('s.product_id')
. ' = ' . $db->quoteName('f.product_id') . ')')
->where($db->quoteName('filter_id')
. ' IN (' . implode(',', $other_ids) . ')');
$query->where('EXISTS (SELECT * FROM (' . $subQuery->__toString() . ') AS t
WHERE ' . $db->quoteName('#__j2store_product_filters.product_id') .
' = ' . $db->quoteName('t.product_id') . ')');
}
However, it's returning too many results: it's still returning all new parts, all brakes, and all tires, instead of just new brakes and new tires.
Here is a demonstration of the conditional logic that I require: db-fiddle.com/f/o1UWTKXVTxxwyvrpcupmqu/3