Joining AND conditions with OR condition on Magento - magento

I am able to run AND and OR boolean conditions on Magento using addFieldToFilter and addAttributeToFilter.
But, I am curious about implementing more complex boolean conditions like below:
WHERE (`sku > 5` AND `price` > '10') OR (`name` = 'books')
for AND condition, I have
$collections = Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect('*')
->addFieldToFilter( 'sku', array('gt' => 5 )
->addFieldToFilter('price', array('gt' => 10);
Which translates to the first parenthesis of the WHERE condition:
(`sku` > 5 AND `price` > 10)
I do not know how to proceed from here to express the OR condition
`name` = 'books'
Any help will be appreciated. Thanks

See my earlier post:
complex boolean conditions on Magento
You can create OR by passing an array:
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('price', array('gt' => 10))
->addAttributeToFilter(
array(
array('attribute'=>'firstname', 'like'=>'test%'),
array('attribute'=>'lastname', 'like'=>'test%'),
)
)
Each additional call to addAttributeToFilter() will ANDed, but firstname / lastname will be ORed.
If you need more complex select statements you can always get the select object from the collection and perform adjustments to the query. Look at Varien_Db_Select for hints :)
$collection->getSelect()->join(..)->orWhere(..); // etc
You can even debug the query to see if it's looking ok:
echo $collection->getSelect()->__toString();

Related

Magento collection - need to amend to make query to make it AND rather than OR

I have the following Collection in Magento :-
$this->addFieldToFilter(array('postcode', 'organisation_name'),array(
array('eq' => $postcode),
array('like' => $lastname. '%')
));
return $this;
This returns a query as follows:
SELECT `main_table`.`organisation_id`, `main_table`.`organisation_id`,
`main_table`.`organisation_type_id`, `main_table`.`organisation_name`, `main_table`.`street`,
`main_table`.`town`, `main_table`.`county`, `main_table`.`country`, `main_table`.`postcode` FROM
`organisation` AS `main_table` WHERE ((postcode = 'AA11AA')
OR (organisation_name LIKE 'jones%'))
LIMIT 1
How do I amend this so it becomes an AND rather than an OR in the SQL query returned?
Try it like this:
$this->addFieldToFilter('postcode',array('eq' => $postcode))
->addFieldToFilter('organisation_name',array('like' => $lastname. '%'))

how to use 'like' instead of '=' in magento collection filter for custom module

i have managed to do this with addFieldToFilter default functionality like this:
$collection->addFieldToFilter(
array('first_name','last_name'),
array($post['firstName'],$post['lastName'])
);
this is working when i print sql (this is just part from the whole statement being printed):
((first_name = 'r') OR (last_name = 't'))
now i am trying to understand how to use 'like' instead of =.
need some help in understanding that.
your time and answers are highly appericiated thank you.
It's weird, but after some researching into your question the solution is quite simple - it's given in the comments in the Magento code:
In the comment for the method addAttributeToFilter() in Mage/Eav/Model/Entity/Collection/Abstract.php (which finally gets called) you can read:
/**
* Add attribute filter to collection
*
* If $attribute is an array will add OR condition with following format:
* array(
* array('attribute'=>'firstname', 'like'=>'test%'),
* array('attribute'=>'lastname', 'like'=>'test%'),
* )
*/
Wasn't quite clear to me what this was supposed to mean, but it's as simple: If you want to add an OR condition between the attributes in your statement, then you have to give your parameter for the addAttributeToFilter() method in this way, so in your case:
$collection->addFieldToFilter(
array(
array('attribute'=>'firstname', 'like'=>$post['firstName']),
array('attribute'=>'lastname', 'like'=>$post['lastName'])
));
You can follow this if you look inside the addAttributeToFilter() method:
if (is_array($attribute)) {
$sqlArr = array();
foreach ($attribute as $condition) {
$sqlArr[] = $this->_getAttributeConditionSql($condition['attribute'], $condition, $joinType);
}
$conditionSql = '('.implode(') OR (', $sqlArr).')';
For you googlers, the rigth way to to it is:
$collection->addFieldToFilter(
array('first_name','last_name'),
array(
array('like' => '%'.$post['firstName'].'%'),
array('like' => '%.'$post['lastName'].'%')
)
);
You should pass an array of fields and an array of conditions.
Generated SQL:
... WHERE ((first_name LIKE '%xxxx%') OR (last_name LIKE '%yyy%')) ...
addFieldToFilter( 'sku', array( "like"=>'abc123' ) )
Here you can read much more about Magento collections: http://alanstorm.com/magento_collections
For example, see section named "AND or OR, or is that OR and AND?" in this article.

Magento, filter collection by date period and include null values

I'm having a difficult time settling up a dates filter on a collection with custom tables. Have searched here and here and some other places but still can not get what I need. The problem is that I can't add the NULL values to the result set.
So far my current code after several trial and error tests:
$myBannersCollection = Mage::getModel('banners/bannersadmin')->getCollection()
->addfieldtofilter('banner_prod_id',$currentProdID)
->addfieldtofilter('banner_start_date',
array(
array('from' => Mage::getModel('core/date')->gmtDate()),
'banner_start_date' => null))
->addfieldtofilter('banner_end_date',
array(
array('gteq' => Mage::getModel('core/date')->gmtDate()),
'null' => true)
);
var_dump((string) $myBannersCollection->getselect());
This code ouputs the following sql snippet:
SELECT `main_table`.*
FROM `dts_banners_admin` AS `main_table`
WHERE (banner_prod_id = '16')
AND (((banner_start_date >= '2012-11-28 14:39:13') OR (banner_start_date='')))
AND (banner_end_date IS NULL)
Have tried several different options to add the NULL condition but no way I can get something like:
SELECT `main_table`.*
FROM `dts_banners_admin` AS `main_table`
WHERE (banner_prod_id = '16')
AND (((banner_start_date>='2012-11-28 14:39:13') OR (banner_start_date IS NULL)))
AND ((banner_end_date >= '2012-11-28 14:39:13') OR (banner_end_date IS NULL))
PS: does Magento has a BETWEEN operator on the addfieldtofilter?
Got it! Thanks to this SO answer. Needed to add another array just for the IS NULL clause. Now the code is:
$myBannersCollection = Mage::getModel('banners/bannersadmin')->getCollection()
->addfieldtofilter('banner_prod_id',$currentProdID)
->addfieldtofilter('banner_start_date',
array(
array('to' => Mage::getModel('core/date')->gmtDate()),
array('banner_start_date', 'null'=>'')))
->addfieldtofilter('banner_end_date',
array(
array('gteq' => Mage::getModel('core/date')->gmtDate()),
array('banner_end_date', 'null'=>''))
);
And outputs this:
SELECT `main_table`.*
FROM `dts_banners_admin` AS `main_table`
WHERE (banner_prod_id = '16')
AND (((banner_start_date>='2012-11-28 15:12:03') OR (banner_start_date IS NULL)))
AND (((banner_end_date >= '2012-11-28 15:12:03') OR (banner_end_date IS NULL)))
EDIT
Modified the banner_start_date as I was using from instead of to and so the period was incorrectly settled up and no data was returned.

complex boolean conditions on Magento

I cannot find the solution to this problem in magento tutorials.
How can I implement the boolean OR operator in custom models when there are two attributes involved? The example in the official tutorial only demonstrated the use of OR boolean for one field, sku.
$filter_a = array('like'=>'a%');
$filter_b = array('like'=>'b%');
Mage::getModel('catalog/product')
->getCollection()
->addFieldToFilter('sku', array($filter_a, $filter_b))
->getSelect();
This translates to
WHERE e.sku like 'a%' or e.sku like 'b%'
But what if I need to run conditions such as :
WHERE (e.sku like 'a%' or e.sku like 'b%') or (table_price.value >= '10' )
How can I do this on Magento? Thanks
You have your syntax incorrec, try this:
Mage::getModel('catalog/product')
->getCollection()
->addAttributeToFilter(
array(
array('attribute'=>'firstname', 'like'=>'test%'),
array('attribute'=>'lastname', 'like'=>'test%'),
)
)
you could replace the attribute names by 'sku' or what ever you wanted. Each array entry will be OR'd.

magento getCollection() can we put where condition?

i am working on a magento project and i need to get the value according to country wise like select address where country ="Nepal"
can we send the where condition in getCollection() function
$collection = Mage::getModel('relocator/location')->getCollection();
any help will be appreciated
got the solution
;P
Mage::getModel('relocator/location')
->getCollection()
->addFilter('country','Nepal');
You can use diffrent condition like below reference from this.
$collection = Mage::getModel('catalog/product')->getCollection();
Is Equal To
$collection->addAttributeToFilter('status', array('eq' => 1));
Greater Than
$collection->addAttributeToFilter('price', array('gt' => 3));
Contains – with % wildcards
Is NULL
$collection->addAttributeToFilter('sku', array('like' => 'DVD%'));
$collection->addAttributeToFilter('entity_id', array('nin' => array(1,2,12)));

Resources