В коллекции Magento есть два метода фильтрации:
- Varien_Data_Collection_Db :: addFieldToFilter
addFieldToFilter ($ field, $ condition = null)
Первый параметр addFieldToFilter
- это атрибут, по которому вы хотите фильтровать. Второе - это значение, которое вы ищете. Вот мы добавляем sku
фильтр для значения n2610
.
Второй параметр также можно использовать для указания типа фильтрации, которую вы хотите выполнить. Здесь все становится немного сложнее, и стоит углубиться в него немного глубже.
Так что по умолчанию следующее
$collection_of_products->addFieldToFilter('sku','n2610');
(по существу) эквивалентно
WHERE sku = "n2610"
Взгляните на себя. Запуск следующего
public function testAction()
{
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku','n2610')
->getSelect());
}
будет давать
SELECT `e`.* FROM `catalog_product_entity` AS `e` WHERE (e.sku = 'n2610')'
Имейте в виду, это может быстро усложниться, если вы используете атрибут EAV. Добавить атрибут
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('*')
->addFieldToFilter('meta_title','my title')
->getSelect()
);
и запрос становится грубым.
SELECT `e`.*, IF(_table_meta_title.value_id>0, _table_meta_title.value, _table_meta_title_default.value) AS `meta_title`
FROM `catalog_product_entity` AS `e`
INNER JOIN `catalog_product_entity_varchar` AS `_table_meta_title_default`
ON (_table_meta_title_default.entity_id = e.entity_id) AND (_table_meta_title_default.attribute_id='103')
AND _table_meta_title_default.store_id=0
LEFT JOIN `catalog_product_entity_varchar` AS `_table_meta_title`
ON (_table_meta_title.entity_id = e.entity_id) AND (_table_meta_title.attribute_id='103')
AND (_table_meta_title.store_id='1')
WHERE (IF(_table_meta_title.value_id>0, _table_meta_title.value, _table_meta_title_default.value) = 'my title')
Не задумываюсь над этим, но стараюсь не слишком задумываться о SQL, если вы находитесь в крайнем сроке.
Другие операторы сравнения Я уверен, что вы задаетесь вопросом «а что, если я хочу что-то, кроме равенства по запросу»? Не равно, больше, меньше, и т. Д. Второй параметр метода addFieldToFilter также охватил вас. Он поддерживает альтернативный синтаксис, в котором вместо передачи строки вы передаете один элемент Array.
Ключ этого массива - это тип сравнения, который вы хотите сделать. Значение, связанное с этим ключом, является значением, по которому вы хотите фильтровать. Давайте повторим вышеупомянутый фильтр, но с этим явным синтаксисом
public function testAction()
{
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku',array('eq'=>'n2610'))
->getSelect()
);
}
Вызов нашего фильтра
addFieldToFilter('sku',array('eq'=>'n2610'))
Как видите, вторым параметром является массив PHP. Его ключ - eq, что означает «равно». Значение этого ключа - n2610, то есть значение, по которому мы фильтруем.
В Magento есть несколько таких английских языковых фильтров, которые принесут слезу памяти (и, возможно, боль) любым старым разработчикам Perl в аудитории.
Ниже перечислены все фильтры, а также пример их SQL-эквивалентов.
array("eq"=>'n2610')
WHERE (e.sku = 'n2610')
array("neq"=>'n2610')
WHERE (e.sku != 'n2610')
array("like"=>'n2610')
WHERE (e.sku like 'n2610')
array("nlike"=>'n2610')
WHERE (e.sku not like 'n2610')
array("is"=>'n2610')
WHERE (e.sku is 'n2610')
array("in"=>array('n2610'))
WHERE (e.sku in ('n2610'))
array("nin"=>array('n2610'))
WHERE (e.sku not in ('n2610'))
array("notnull"=>'n2610')
WHERE (e.sku is NOT NULL)
array("null"=>'n2610')
WHERE (e.sku is NULL)
array("gt"=>'n2610')
WHERE (e.sku > 'n2610')
array("lt"=>'n2610')
WHERE (e.sku < 'n2610')
array("gteq"=>'n2610')
WHERE (e.sku >= 'n2610')
array("moreq"=>'n2610') //a weird, second way to do greater than equal
WHERE (e.sku >= 'n2610')
array("lteq"=>'n2610')
WHERE (e.sku <= 'n2610')
array("finset"=>array('n2610'))
WHERE (find_in_set('n2610',e.sku))
array('from'=>'10','to'=>'20')
WHERE e.sku >= '10' and e.sku <= '20'
Большинство из них говорят сами за себя, но некоторые заслуживают особого
in, nin, find_in_set Условные выражения in и nin позволяют передавать массив значений. То есть порция значения вашего массива фильтра сама по себе может быть массивом.
array("in"=>array('n2610','ABC123')
WHERE (e.sku in ('n2610','ABC123'))
notnull, null Ключевое слово NULL является особенным в большинстве разновидностей SQL. Как правило, это не будет хорошо работать со стандартным оператором равенства (=). Если в качестве типа фильтра указать notnull или null, вы получите правильный синтаксис для сравнения NULL, игнорируя при этом любое передаваемое вами значение.
array("notnull"=>'n2610')
WHERE (e.sku is NOT NULL)
from - to filter Это еще один специальный формат, который нарушает стандартное правило. Вместо одного элемента массива вы указываете массив из двух элементов. Один элемент имеет ключ от, другой элемент имеет ключ. Как указали клавиши, этот фильтр позволяет вам строить диапазон от / до, не беспокоясь о символах больше или меньше
public function testAction
{
var_dump(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('price',array('from'=>'10','to'=>'20'))
->getSelect()
);
}
Вышеуказанные урожаи
WHERE (_table_price.value >= '10' and _table_price.value <= '20')'
И или ИЛИ, или это ИЛИ и И? Наконец, мы подошли к логическим операторам. Это редкий момент, когда мы фильтруем только по одному атрибуту. К счастью, в коллекциях Magento есть информация. Вы можете объединить несколько вызовов в addFieldToFilter, чтобы получить несколько запросов «И».
function testAction()
{
echo(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku',array('like'=>'a%'))
->addFieldToFilter('sku',array('like'=>'b%'))
->getSelect()
);
}
Объединяя несколько вызовов, как описано выше, мы создадим предложение where, которое выглядит примерно так:
WHERE (e.sku like 'a%') AND (e.sku like 'b%')
Тем из вас, кто только что поднял руку, да, приведенный выше пример всегда будет возвращать 0 записей. Никакое sku не может начинаться с ОБА a и a b. То, что мы, вероятно, хотим здесь, это запрос OR. Это подводит нас к еще одному запутанному аспекту второго параметра addFieldToFilter.
Если вы хотите построить запрос ИЛИ, вам нужно передать массив массивов фильтров в качестве второго параметра. Я считаю, что лучше назначить ваши отдельные массивы фильтров для переменных
public function testAction()
{
$filter_a = array('like'=>'a%');
$filter_b = array('like'=>'b%');
}
а затем назначить массив всех моих переменных фильтра
public function testAction()
{
$filter_a = array('like'=>'a%');
$filter_b = array('like'=>'b%');
echo(
(string)
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku',array($filter_a,$filter_b))
->getSelect()
);
}
В целях ясности, вот вышеупомянутый массив массивов фильтров.
array($filter_a,$filter_b)
Это даст нам предложение WHERE, которое выглядит примерно так:
WHERE (((e.sku like 'a%') or (e.sku like 'b%')))
- Varien_Data_Collection :: AddFilter
addFilter($field, $value, $type = 'and')
addFilter()
позволяет фильтровать только одно поле по одному значению и типу. $type
может быть любым из:
- "and" (по умолчанию) - добавляет AND $ field = $ value к предложению WHERE
- "or" - добавляет "OR $ field = $ value к предложению WHERE
Посмотреть подробнее
addFilter
сattributes
?