Thursday, April 26, 2012

Magento: Sort latest product by ‘created date’


Use following code to sort/order product by created date
$todayDate  = Mage::app()->getLocale()->date()->toString(Varien_Date::DATETIME_INTERNAL_FORMAT);
$collection = Mage::getModel('catalog/product')
              ->getCollection()
              ->addAttributeToFilter('news_from_date', array('date' => true, 'to' => $todayDate))
              ->addAttributeToFilter('news_to_date', array('or'=> array(
                        0 => array('date' => true, 'from' => $todayDate),
                        1 => array('is' => new Zend_Db_Expr('null')))
                    ), 'left')
              ->addAttributeToSort('news_from_date', 'desc')
              ->addAttributeToSort('created_at', 'desc');

Magento : Set Random Order in Collection


we can select random rows from MySQL table using Zend_Db_Expr(‘RAND()’),
here we have to create a new function in module collection class
(Namespace/Module/Model/Mysql4/Module/Collection.php)
public function setRandomOrder()
{
    $this->getSelect()->order(new Zend_Db_Expr('RAND()'));
    return $this;
}
And use it as
$collection = Mage::getModel('test/test')
                    ->getCollection()
                    ->setRandomOrder();

Collection in magento


Here, I am going to explain some database interaction functions present in the class Mage_Eav_Model_Entity_Collection_Abstract. These collection functions are very useful to select data from Magento database. We need them almost all the time for filtering collection object.


Below are some of the useful functions that we use most often.

Class: Mage_Eav_Model_Entity_Collection_Abstract

addAttributeToFilter: adds WHERE clause on $attribute specified by $condition

/**
* 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%’),
* )
*
* @see self::_getConditionSql for $condition
* @param Mage_Eav_Model_Entity_Attribute_Interface|integer|string|array $attribute
* @param null|string|array $condition
* @param string $operator
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
addAttributeToFilter($attribute, $condition=null, $joinType=’inner’)

addAttributeToSelect: gets the value for $attribute in the SELECT clause; specify * to get all attributes (i.e. to execute SELECT *)

/**
* Add attribute to entities in collection
*
* If $attribute==’*’ select all attributes
*
* @param array|string|integer|Mage_Core_Model_Config_Element $attribute
* @param false|string $joinType flag for joining attribute
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
addAttributeToSelect($attribute, $joinType=false)

If an array is passed but no attribute code specified, it will be interpreted as a group of OR conditions that will be processed in the same way.
If no attribute code is specified, it defaults to eq.

$collection = Mage::getModel('catalog/product')->getCollection();

// select all attributes
$collection->addAttributeToSelect('*');

// select specific attributes
$collection->addAttributeToSelect(array('name', 'url_key', 'type_id'));

// select only those items whose status = 1
$collection->addAttributeToFilter('status', 1);

// alternative to select only those items whose status = 1
$collection->addAttributeToFilter('status', array('eq' => 1));

// using LIKE statement
$collection->addAttributeToFilter('sku', array('like' => '%CH%'));

// using IN statement,
// i.e. selecting only those items whose ID fall in the given array
$collection->addAttributeToFilter('id', array('in' => array(1, 14, 51, 52)));

// selecting only those items whose ID is greater than the given value
$collection->addAttributeToFilter('id', array('gt' => 5));

// select by date range
$collection->addAttributeToFilter('date_field', array(
    'from' => '10 September 2010',
    'from' => '21 September 2010',
    'date' => true, // specifies conversion of comparison values
    ));

// Add OR condition:
$collection->addAttributeToFilter(array(
    array(
        'attribute' => 'field_name',
        'in'        => array(1, 2, 3),
        ),
    array(
        'attribute' => 'date_field',
        'from'      => '2010-09-10',
        ),
    ));
Below is the full filter condition codes with attribute code and its sql equivalent

eq : =
neq : !=
like : LIKE
nlike : NOT LIKE
in : IN ()
nin : NOT IN ()
is : IS
notnull : IS NOT NULL
null : IS NULL
moreq : >=
gt : >
lt : <
gteq : >=
lteq : <=
finset : FIND_IN_SET()
from : >= (for use with dates)
to : <= (for use with dates)
date : optional flag for use with from/to to specify that comparison value should first be converted to a date
datetime : optional flag for use with from/to to specify that comparison value should first be converted to a datetime

addFieldToFilter: alias for addAttributeToFilter(). This filters the database table fields.

/**
* Wrapper for compatibility with Varien_Data_Collection_Db
*
* @param mixed $attribute
* @param mixed $condition
*/
addFieldToFilter($attribute, $condition=null)

addAttributeToSort: adds ORDER BY clause on $attribute

/**
* Add attribute to sort order
*
* @param string $attribute
* @param string $dir
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
addAttributeToSort($attribute, $dir=’asc’)

addExpressionAttributeToSelect: adds SQL expression $expression, using $alias, to SELECT clause (typically containing aggregate functions such as SUM(), COUNT()); when $attribute specifies a single attribute as a string, $expression can reference the attribute as simply {{attribute}}, but when passing an array of attributes, each attribute must be referenced in $expression by the name of the specific attribute;

/**
* Add attribute expression (SUM, COUNT, etc)
*
* Example: (‘sub_total’, ‘SUM({{attribute}})’, ‘revenue’)
* Example: (‘sub_total’, ‘SUM({{revenue}})’, ‘revenue’)
*
* For some functions like SUM use groupByAttribute.
*
* @param string $alias
* @param string $expression
* @param string $attribute
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
addExpressionAttributeToSelect($alias, $expression, $attribute)

groupByAttribute: adds $attribute to GROUP BY clause

/**
* Groups results by specified attribute
*
* @param string|array $attribute
*/
groupByAttribute($attribute)

joinAttribute: joins another entity and adds attribute from joined entity, using $alias, to SELECT clause.

Here are the parameters for joinAttribute function:-

$alias = selected field name. You can keep it’s name whatever you want.

$attribute = joined entity type code and attribute code = entity_type_code/attribute_code
entity_type_code is present in eav_entity_type table
attribute_code is present in eav_attribute table
attribute_code is attribute of the corresponding entity you want to select out.

$bind = attribute code of the main entity to link to the joined entity.

$filter = primary key for the joined entity (entity_id default)

/**
* Add attribute from joined entity to select
*
* Examples:
* (‘billing_firstname’, ‘customer_address/firstname’, ‘default_billing’)
* (‘billing_lastname’, ‘customer_address/lastname’, ‘default_billing’)
* (‘shipping_lastname’, ‘customer_address/lastname’, ‘default_billing’)
* (‘shipping_postalcode’, ‘customer_address/postalcode’, ‘default_shipping’)
* (‘shipping_city’, $cityAttribute, ‘default_shipping’)
*
* Developer is encouraged to use existing instances of attributes and entities
* After first use of string entity name it will be cached in the collection
*
* @todo connect between joined attributes of same entity
* @param string $alias alias for the joined attribute
* @param string|Mage_Eav_Model_Entity_Attribute_Abstract $attribute
* @param string $bind attribute of the main entity to link with joined $filter
* @param string $filter primary key for the joined entity (entity_id default)
* @param string $joinType inner|left
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
joinAttribute($alias, $attribute, $bind, $filter=null, $joinType=’inner’, $storeId=null)

joinTable: joins table $table

Here are the parameters of the function joinTable:-

$table = table name to join
$bind = ( parent_key = foreign_key )
$fields = array of fields to select
$cond = where condition
$joinType = join type

/**
* Join a table
*
* @param string|array $table
* @param string $bind
* @param string|array $fields
* @param null|array $cond
* @param string $joinType
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
joinTable($table, $bind, $fields=null, $cond=null, $joinType=’inner’)

Using joinAttribute and joinTable

In the code below, all order invoice items are selected, i.e. all products that have been invoiced.
joinTable is used to join sales_order_entity table to fetch increment_id and store_id of the invoice for each product.
joinAttribute is used to fetch order_id, product_name, and store_id.
joinTable is used again to fetch the order status of each invoice item.

$collection = Mage::getModel('sales/order_invoice_item')
                    ->getCollection()
                    ->joinTable('sales_order_entity', 'entity_id=parent_id', array('invoice_id'=>'increment_id', 'store_id' => 'store_id'), null , 'left')
                    ->joinAttribute('order_id', 'invoice/order_id', 'parent_id', null, 'left')
                    ->joinAttribute('product_name', 'invoice_item/name', 'entity_id', null, 'left')
                    ->joinAttribute('store_id', 'invoice/store_id', 'parent_id', null, 'left')

                    ->joinTable('sales_order', 'entity_id=order_id', array('order_status'=>'status'), null , 'left')
                    ;
joinField: joins regular table field using an attribute as foreign key

/**
* Join regular table field and use an attribute as fk
*
* Examples:
* (‘country_name’, ‘directory/country_name’, ‘name’, ‘country_id=shipping_country’, “{{table}}.language_code=’en’”, ‘left’)
*
* @param string $alias ‘country_name’
* @param string $table ‘directory/country_name’
* @param string $field ‘name’
* @param string $bind ‘PK(country_id)=FK(shipping_country_id)’
* @param string|array $cond “{{table}}.language_code=’en’” OR array(‘language_code’=>’en’)
* @param string $joinType ‘left’
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
joinField($alias, $table, $field, $bind, $cond=null, $joinType=’inner’)

removeAttributeToSelect: removes $attribute from SELECT clause; specify null to remove all attributes

/**
* Remove an attribute from selection list
*
* @param string $attribute
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
removeAttributeToSelect($attribute=null)

setPage: sets LIMIT clause by specifying page number (one-indexed) and number of records per page; equivalent to calling setCurPage($pageNum) and setPageSize($pageSize)

/**
* Set collection page start and records to show
*
* @param integer $pageNum
* @param integer $pageSize
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
setPage($pageNum, $pageSize)

importFromArray: imports 2D array into collection as objects

/**
* Import 2D array into collection as objects
*
* If the imported items already exist, update the data for existing objects
*
* @param array $arr
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
importFromArray($arr)

exportToArray: returns collection data as a 2D array

/**
* Get collection data as a 2D array
*
* @return array
*/
exportToArray()

setOrder: alias for addAttributeToSort() q.v., identical except that it can accept array of attributes, and default $dir is desc

/**
* Set sorting order
*
* $attribute can also be an array of attributes
*
* @param string|array $attribute
* @param string $dir
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
setOrder($attribute, $dir=’desc’)

Very Useful Collection Functions


There are different important functions that you can implement in your Collection object. The functions are present in Varien_Data_Collection_Db class. The class file is present in lib/Varien/Data/Collection/Db.php

Here are some of the functions that you can use in your collection object:-


/**
 * Get Zend_Db_Select instance
 */
$collection->getSelect();

/**
 * Get collection size
 */
$collection->getSelect()->getSize();

/**
 * Get sql select string or object
 */
$collection->getSelect()->getSelectSql();

/**
 * Add select order
 */
$collection->getSelect()->setOrder($field, $direction);

/**
 * Add field 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%'),
 * )
 */
$collection->getSelect()->setOrder($field, $condition);

/**
 * Set select distinct
 */
$collection->getSelect()->distinct($flag);

/**
 * Get all data array for collection
 */
$collection->getSelect()->getData();

/**
 * Reset loaded for collection data array
 */
$collection->getSelect()->resetData();

/**
 * Print and/or log query
 */
$collection->getSelect()->printLogQuery(true, true);
More functions below:-

Varien_Data_Collection_Db class extends Varien_Data_Collection class. Here are some more functions present in Varien_Data_Collection class:-

/**
 * Get current collection page
 */
$collection->getSelect()->getCurPage();

/**
 * Retrieve collection last page number
 */
$collection->getSelect()->getLastPageNumber();

/**
 * Retrieve collection page size
 */
$collection->getSelect()->getPageSize();

/**
 * Retrieve collection all items count
 */
$collection->getSelect()->getSize();

/**
 * Retrieve collection first item
 */
$collection->getSelect()->getFirstItem();

/**
 * Retrieve collection last item
 */
$collection->getSelect()->getLastItem();

/**
 * Retrieve collection items
 */
$collection->getSelect()->getItems();

/**
 * Clear collection
 */
$collection->getSelect()->clear();
You can also use the select functions as present in Zend_Db_Select class. This class file is present in lib/Zend/Db/Select.php


http://blog.chapagain.com.np/category/magento/page/5/

Adding OR and AND query condition to collection






// PRODUCT COLLECTION
$collection = Mage::getModel('catalog/product')->getCollection();
Adding AND query condition


Filtering collection to select only those products whose sku is like ‘ch’ AND status is equal to 1 (i.e. enabled status).


// AND QUERY
$collection->addAttributeToFilter('sku', array('like' => '%ch%'));
$collection->addAttributeToFilter('status', array('eq' => '1'));
Adding OR query condition


Filtering collection to select only those products whose sku is like ‘ch’ OR status is equal to 1 (i.e. enabled status).


// OR QUERY
$collection->addAttributeToFilter(array(
                array(
                    'attribute' => 'sku',
                    'like' => '%ch%'),
                array(
                    'attribute' => 'status',
                    'eq' => '1')
            ));
You may check the query statement with the following code


$collection->printLogQuery(true);

http://blog.chapagain.com.np/magento-adding-or-and-and-query-to-collection/

Upgrading mysql setup of a module in magento


Suppose, you have a module called MyModule. Its version is 0.1.0. Now, you want to do some database changes for the module. You have the mysql setup file (mysql install file) mysql4-install-0.1.0.php in MyModule/sql/mymodule_setup folder of your module.

You don’t need to make direct changes to database. You can upgrade your module to make your necessary database changes. To do so,


1) You need to create a new mysql upgrade file inside MyModule/sql/mymodule_setup folder.

Let us suppose that you are going to change the version of your module from 0.1.0 to 0.1.1.

The mysql upgrade file name should be mysql4-upgrade-0.1.0-0.1.1.php

The upgrade format is like mysql4-upgrade-CURRENT_VERSION-UPGRADED_VERSION.php

2) Write necessary sql statements in the newly added mysql upgrade file.

3) You have to change the version in MyModule/etc/config.xml as well.

Change the version like 0.1.1. 0.1.1 is the new version for our module.

4) Reload your site. And you are done!

http://blog.chapagain.com.np/magento-upgrading-mysql-setup-of-a-module/

Magento: How to upload file


Attribute in Magento is like a property. All Products, Categories, Orders, Customers, etc. have attributes. For example, the attribute of a product is its name, sku, description, image, etc.

This article will show you how to get attribute name and value for any product.


The following code is about getting attribute collection and then fetching that attribute’s name, value, type, and other parameters.

Note: The attribute code in the case below is my_attribute.

/**
 * get attribute collection
 */
$attribute = $_product->getResource()->getAttribute('my_attribute');
/**
 * get attribute type
 */
$attribute->getAttributeType();
/**
 * get attribute Label
 */
$attribute->getFrontendLabel();
/**
 * get attribute default value
 */
$attribute->getDefaultValue();
/**
 * check if the attribute is visible
 */
$attribute->getIsVisible();
/**
 * check if the attribute is required
 */
$attribute->getIsRequired();
/**
 * get attribute value
 */
$attributeValue = Mage::getModel('catalog/product')->load($_product->getId())->getMyAttribute();
Here is the code to fetch value from a select box attribute:-

Note: I suppose the attribute code to be ‘my_attribute‘

$attributeValue = Mage::getModel('catalog/product')
                            ->load($_product->getId())
                            ->getAttributeText('my_attribute');
Load any particular attribute by attribute code

Here is the code to get data of any particular attribute by the attribute code.

$attributeInfo = Mage::getResourceModel('eav/entity_attribute_collection')
                        ->setCodeFilter(YOUR_ATTRIBUTE_CODE)
                        ->getFirstItem();

// echo "<pre>"; print_r($attributeInfo->getData()); echo "</pre>";
Get all option value list for the particular attribute

You can see above that I got attribute information by attribute code. My attribute information is stored as $attributeInfo.

Here is the code to get all option values for my attribute $attributeInfo.

$attributeOptions = $attributeInfo->getSource()->getAllOptions(false);
// echo "<pre>"; print_r($attributeOptions); echo "</pre>";
Get attribute’s option information by option id

I have my attribute as $attributeInfo.
I have my attribute’s option value array as $attributeOptions.

Suppose, I want to get detail information of any option listed in $attributeOptions array. Here is the code to do so:-

$attributeId = $attributeInfo->getAttributeId();
$optionId = YOUR_ATTRIBUTE_OPTION_ID;

$attributeOptionSingle = Mage::getResourceModel('eav/entity_attribute_option_collection')
                                    ->setPositionOrder('asc')
                                    ->setAttributeFilter($attributeId)
                                    ->setIdFilter($optionId)
                                    ->setStoreFilter()
                                    ->load()
                                    ->getFirstItem();

// echo "<pre>"; print_r($attributeOptionSingle); echo "</pre>";
Get attribute of particular entity type

Here, I am going to get information about ‘order_id’ attribute of ‘invoice’ entity type.

$entityType = Mage::getModel('eav/config')->getEntityType('invoice');
$entityTypeId = $entityType->getEntityTypeId();

$attribute = Mage::getResourceModel('eav/entity_attribute_collection')
                ->setCodeFilter('order_id')
                ->setEntityTypeFilter($entityTypeId)
                ->getFirstItem();
Get attribute options of Configurable product

$confAttributes = $_product->getTypeInstance(true)->getConfigurableAttributesAsArray($_product);
Hope this helps. Thanks.

Magento: Delete System Attribute



To delete the attribute, you have to make it user defined
using 'eav_attribute table' by seting the field 'is_user_defined'
to 1.Now we can delete it from Attribute management

Sunday, April 22, 2012

Magento performance tips



During the development of your Magento eCommerce store, performance usually takes a back seat to functionality and design. However, after you’ve installed all of your extensions and have checked the spelling on your last cms page, you’ll want to focus your attention on making your shop as responsive as possible for your customers. Granted, it pays to have a terrific hosting provider that understands how to optimize the server environment, but there are also some things you can do on your end to minimize latency and make your shop run as efficiently as possible.
Tip 1: Tweak your .htaccess file:
Magento’s .htaccess file comes pre-configured with a few tweaks to make your pages load faster, but because hosting environments differ, many of these are commented out or set to low defaults.
1. Turn on output compression
mod_deflate is enabled on all of our servers. This module compresses your text-based files prior to sending them over the network. The customer’s browser then automatically uncompresses them prior to displaying them to the user. To enable this uncomment the appropriate lines as follows:
<IfModule mod_deflate.c>

############################################
## enable apache served files compression
## http://developer.yahoo.com/performance/rules.html#gzip

 # Insert filter on all content
 SetOutputFilter DEFLATE
 # Insert filter on selected content types only
 AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript

 # Netscape 4.x has some problems...
 BrowserMatch ^Mozilla/4 gzip-only-text/html

 # Netscape 4.06-4.08 have some more problems
 BrowserMatch ^Mozilla/4\.0[678] no-gzip

 # MSIE masquerades as Netscape, but it is fine
 BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

 # Don't compress images
 SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary

 # Make sure proxies don't deliver the wrong content
 Header append Vary User-Agent env=!dont-vary

</IfModule>
2. Enable far-future expires
Some content, such as images and css, don’t change all that often. For content such as this, you can improve performance by taking advantage of a web browser’s caching behavior. Setting far-future expires headers will allow web browsers to cache images and other static files so that upon subsequent visits, they won’t have to be re-downloaded.

<IfModule mod_expires.c>

############################################
## Add default Expires header
## http://developer.yahoo.com/performance/rules.html#expires

 ExpiresActive On
 ExpiresDefault "access plus 1 year"

</IfModule>
Tip 2: Refresh your indexes
Magento keeps indexes of some of your data in special tables to make queries more efficient. When you were developing your store, you were adding and deleting products, categories, urls, etc. This activity causes your indexes to have gaps and stale data. When you’re ready to go live, you’ll want to refresh all of your indexes in order to rebuild those tables.
There are two ways to do this: from your Admin dashboard or from the command line. To rebuild your indexes from your Magento Admin panel, just go to System > Index Management, select All, select Reindex Data, and then click Submit.
It’s also possible to rebuild your indexes from the command line using the shell tools included in Magento versions 1.4 and higher. These tools are located in your MAGENTO_ROOT/shell/ directory and can be run with a call to php’s command line interface:
$ php -f indexer.php help
Usage:  php -f indexer.php -- [options]

 --status <indexer>            Show Indexer(s) Status
 --mode <indexer>              Show Indexer(s) Index Mode
 --mode-realtime <indexer>     Set index mode type "Update on Save"
 --mode-manual <indexer>       Set index mode type "Manual Update"
 --reindex <indexer>           Reindex Data
 info                          Show allowed indexers
 reindexall                    Reindex Data by all indexers
 help                          This help

 <indexer>     Comma separated indexer codes or value "all" for all indexers
As you can see, the same functionality that can be found in the Admin panel under Index Management can be found here. To rebuild all of your indexes, just enter:
$ php -f indexer.php reindexall
Tip 3: Turn on caching
When you’re developing your site, you probably turned off Magento’s native cache so that you would be able to see your design changes instantly. Now that you’ve finalized your design work, make sure you turn the cache back on. This improves performance 5-10 times over the cache being off.
Ever wonder what gets cached? Here’s an overview:
Configuration files (xml)
Layouts (xml)
HTML blocks for Top Navigation, and Footer
Translations stored as an array
Data collections for Website, Store, and Store View
Tip 4: Use the Flat Catalog feature
Magento makes heavy use of the EAV model for storing customer, product, and category data in its database. The main benefit of the EAV model is that it allows for completely extensible attributes for those objects. The main drawback is that those attributes are stored in multiple tables rather than one very large table. This means that SQL queries need to be longer and more complex. Using the Flat Catalog feature creates new tables where each row contains all of the necessary data about a product or category. You can imagine that this makes the SQL queries much more efficient.
The Flat Catalog for Categories should be used for all Magento shops. The Flat Catalog for Products only begins to show a performance benefit once you’ve reached the 1000 SKU point. You can enable both of these in the back end:
Go to System > Index Management and make sure “Product Flat Data” and “Category Flat Data” are built and ready.
Go to System > Configuration > Catalog > FrontEnd and select “Yes” for Use Flat Catalog Category and (if desired) Use Flat Catalog Product.
Tip 5: Enable the Mage Compiler
This is a new feature introduced in version 1.3.2.x and bundled with 1.4.x, although it is still listed as “beta”. To understand how this feature can help improve your site’s performance, you have to understand what happens when a browser requests a URL from Magento. By default, and for every request, magento will look in the following directories, in the following order:
app/code/local/
app/code/community/
app/code/core/
lib/
This is what gives you, the developer, the wonderful ability to override and extend Magento to your heart’s content. If you want to change or modify some class, you just put your code in app/code/local/ and Magento will find it first and run it instead of the core definition in app/code/core.
As great as this is, it results in a great deal of disk I/O for every request. That’s where the Mage Compiler comes it. It essentially copies all of the class definitions and code found under app/code into a singe directory: includes/src/. It then gets rid of all of the other include paths and replaces them with the one. This way, Magento only needs to search one directory rather than four for each request.
It’s important to compile after you’ve finished installing your modules and developing your custom code if you want this to work properly. This too can be enabled either in the Admin panel or on the command line. In the Magento Admin, go to System > Tools > Compilation, and click Run Compilation Process. To run from the command line, use the following syntax (script is also located in the MAGENTO_ROOT/shell directory):
$ php -f compiler.php help
Usage:  php -f compiler.php -- [options]

  state         Show Compilation State
  compile       Run Compilation Process
  clear         Disable Compiler include path and Remove compiled files
  enable        Enable Compiler include path
  disable       Disable Compiler include path
  help          This help
Tip 6: Make use of parallel downloads to speed page rendering
Most web browsers limit the number of concurrent downloads to around 4 for each unique URL found in a web page. If all of your content is coming from the same host, this limitation can introduce unnecessary delays in rendering the page. You can trick the browser into downloading your content in parallel by using Pointer Domains and Magento’s base url settings.
Let’s say your awesome eCommerce store is located at http://www.example.com/. Your media, skin, and javascript URLs will therefore be http://www.example.com/media, http://www.example.com/skin/, and http://www.example.com/js/, respectively. What you want to do is create different host names for your media, skin, and js URLS that point to the same Magento installation as the www host.
You can do this in your Siteworx control panel under Hosting Features > Domains > Pointer Domains. Create pointer domains called media.example.com, js.example.com, and skin.example.com. Or, you can just create static.example.com. Next, log in to your Magento Admin panel and go to System > Configuration > Web, and change the secure and unsecure base urls for the media, skin, and js options to the pointer domains you just created. Your final configuration should look like the following:
Base URL: http://www.example.com/
Base Link URL: http://www.example.com/
Base Skin URL: http://skin.example.com/skin/
Base Media URL: http://media.example.com/media/
Base Javascript URL: http://js.example.com/js/
Now, go load your page. If you watch the status bar, you’ll notice that your static content, such as images and javascript, is being pulled from the domains you just created, while the main HTML is being pulled from the www URL. In reality these are all located on the exact same server, but the benefit is on the client side, and they don’t need to know that.

Friday, April 20, 2012

addAttributeToFilter Conditionals In Magento



addAttributeToFilter is a function that can be called on a product collection in Magento. In short, it adds a condition to the WHERE part of the MySQL query used to extract a product collection from the database.


$_products = Mage::getModel('catalog/product')->getCollection()
   ->addAttributeToSelect(array('name', 'product_url', 'small_image'))
   ->addAttributeToFilter('sku', array('like' => 'UX%'))
    ->load();

The above code would get a product collection, with each product having it's name, url, price and small image loaded in it's data array. The product collection would be filtered and contain only products that have an SKU starting with UX.
addAttributeToFilter Conditionals

Notice above, I used the LIKE operator? There are many more operators in SQL and addAttributeToFilter will accept them all. I include them below as well as a reference for you. Hopefully this will save you some time.
Equals: eq

$_products->addAttributeToFilter('status', array('eq' => 1));
Not Equals - neq


$_products->addAttributeToFilter('sku', array('neq' => 'test-product'));
Like - like

$_products->addAttributeToFilter('sku', array('like' => 'UX%'));

One thing to note about like is that you can include SQL wildcard characters such as the percent sign.
Not Like - nlike

$_products->addAttributeToFilter('sku', array('nlike' => 'err-prod%'));
In - in


$_products->addAttributeToFilter('id', array('in' => array(1,4,74,98)));

When using in, the value parameter accepts an array of values.
Not In - nin

$_products->addAttributeToFilter('id', array('nin' => array(1,4,74,98)));
NULL - null

$_products->addAttributeToFilter('description', 'null');
Not NULL - notnull

$_products->addAttributeToFilter('description', 'notnull');
Greater Than - gt

$_products->addAttributeToFilter('id', array('gt' => 5));
Less Than - lt

$_products->addAttributeToFilter('id', array('lt' => 5));
Greater Than or Equals To- gteq

$_products->addAttributeToFilter('id', array('gteq' => 5));
Less Than or Equals To - lteq

$_products->addAttributeToFilter('id', array('lteq' => 5));
addFieldToFilter()

As far as I'm aware, addAttributeToFilter only works with products in Magento. When I first found out this fact I was not only shocked, I was worried! I thought that without it, I would have to custom craft all of my SQL queries. After scouring the Magento core code one night, I found addFieldToFilter(). This functions works in the exact same way and takes the same paramters, however it works on ALL collections and not just on products!
Debugging The SQL Query

There are two ways to debug the query being executed when loading a collection in Magento.


// Method 1
Mage::getModel('catalog/product')->getCollection()->load(true);

// Method 2 (Quicker, Recommended)
$collection = Mage::getModel('catalog/product')->getCollection();
echo $collection->getSelect();

Both method 1 and method 2 will print out the query but both will do it in slightly different ways. Method 1 prints the query out as well as loading the products while method 2 will just convert the query object to a string (ie. will print out the SQL). The second method is definitely better as it will be executed much quicker but I include them both here for reference.



Here, I am going to explain some database interaction functions present in the class Mage_Eav_Model_Entity_Collection_Abstract. These collection functions are very useful to select data from Magento database. We need them almost all the time for filtering collection object.


Below are some of the useful functions that we use most often.

Class: Mage_Eav_Model_Entity_Collection_Abstract

addAttributeToFilter: adds WHERE clause on $attribute specified by $condition

/**
* 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%’),
* )
*
* @see self::_getConditionSql for $condition
* @param Mage_Eav_Model_Entity_Attribute_Interface|integer|string|array $attribute
* @param null|string|array $condition
* @param string $operator
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
addAttributeToFilter($attribute, $condition=null, $joinType=’inner’)

addAttributeToSelect: gets the value for $attribute in the SELECT clause; specify * to get all attributes (i.e. to execute SELECT *)

/**
* Add attribute to entities in collection
*
* If $attribute==’*’ select all attributes
*
* @param array|string|integer|Mage_Core_Model_Config_Element $attribute
* @param false|string $joinType flag for joining attribute
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
addAttributeToSelect($attribute, $joinType=false)

If an array is passed but no attribute code specified, it will be interpreted as a group of OR conditions that will be processed in the same way.
If no attribute code is specified, it defaults to eq.

$collection = Mage::getModel('catalog/product')->getCollection();

// select all attributes
$collection->addAttributeToSelect('*');

// select specific attributes
$collection->addAttributeToSelect(array('name', 'url_key', 'type_id'));

// select only those items whose status = 1
$collection->addAttributeToFilter('status', 1);

// alternative to select only those items whose status = 1
$collection->addAttributeToFilter('status', array('eq' => 1));

// using LIKE statement
$collection->addAttributeToFilter('sku', array('like' => '%CH%'));

// using IN statement,
// i.e. selecting only those items whose ID fall in the given array
$collection->addAttributeToFilter('id', array('in' => array(1, 14, 51, 52)));

// selecting only those items whose ID is greater than the given value
$collection->addAttributeToFilter('id', array('gt' => 5));

// select by date range
$collection->addAttributeToFilter('date_field', array(
    'from' => '10 September 2010',
    'from' => '21 September 2010',
    'date' => true, // specifies conversion of comparison values
    ));

// Add OR condition:
$collection->addAttributeToFilter(array(
    array(
        'attribute' => 'field_name',
        'in'        => array(1, 2, 3),
        ),
    array(
        'attribute' => 'date_field',
        'from'      => '2010-09-10',
        ),
    ));
Below is the full filter condition codes with attribute code and its sql equivalent

eq : =
neq : !=
like : LIKE
nlike : NOT LIKE
in : IN ()
nin : NOT IN ()
is : IS
notnull : IS NOT NULL
null : IS NULL
moreq : >=
gt : >
lt : <
gteq : >=
lteq : <=
finset : FIND_IN_SET()
from : >= (for use with dates)
to : <= (for use with dates)
date : optional flag for use with from/to to specify that comparison value should first be converted to a date
datetime : optional flag for use with from/to to specify that comparison value should first be converted to a datetime

addFieldToFilter: alias for addAttributeToFilter(). This filters the database table fields.

/**
* Wrapper for compatibility with Varien_Data_Collection_Db
*
* @param mixed $attribute
* @param mixed $condition
*/
addFieldToFilter($attribute, $condition=null)

addAttributeToSort: adds ORDER BY clause on $attribute

/**
* Add attribute to sort order
*
* @param string $attribute
* @param string $dir
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
addAttributeToSort($attribute, $dir=’asc’)

addExpressionAttributeToSelect: adds SQL expression $expression, using $alias, to SELECT clause (typically containing aggregate functions such as SUM(), COUNT()); when $attribute specifies a single attribute as a string, $expression can reference the attribute as simply {{attribute}}, but when passing an array of attributes, each attribute must be referenced in $expression by the name of the specific attribute;

/**
* Add attribute expression (SUM, COUNT, etc)
*
* Example: (‘sub_total’, ‘SUM({{attribute}})’, ‘revenue’)
* Example: (‘sub_total’, ‘SUM({{revenue}})’, ‘revenue’)
*
* For some functions like SUM use groupByAttribute.
*
* @param string $alias
* @param string $expression
* @param string $attribute
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
addExpressionAttributeToSelect($alias, $expression, $attribute)

groupByAttribute: adds $attribute to GROUP BY clause

/**
* Groups results by specified attribute
*
* @param string|array $attribute
*/
groupByAttribute($attribute)

joinAttribute: joins another entity and adds attribute from joined entity, using $alias, to SELECT clause.

Here are the parameters for joinAttribute function:-

$alias = selected field name. You can keep it’s name whatever you want.

$attribute = joined entity type code and attribute code = entity_type_code/attribute_code
entity_type_code is present in eav_entity_type table
attribute_code is present in eav_attribute table
attribute_code is attribute of the corresponding entity you want to select out.

$bind = attribute code of the main entity to link to the joined entity.

$filter = primary key for the joined entity (entity_id default)

/**
* Add attribute from joined entity to select
*
* Examples:
* (‘billing_firstname’, ‘customer_address/firstname’, ‘default_billing’)
* (‘billing_lastname’, ‘customer_address/lastname’, ‘default_billing’)
* (‘shipping_lastname’, ‘customer_address/lastname’, ‘default_billing’)
* (‘shipping_postalcode’, ‘customer_address/postalcode’, ‘default_shipping’)
* (‘shipping_city’, $cityAttribute, ‘default_shipping’)
*
* Developer is encouraged to use existing instances of attributes and entities
* After first use of string entity name it will be cached in the collection
*
* @todo connect between joined attributes of same entity
* @param string $alias alias for the joined attribute
* @param string|Mage_Eav_Model_Entity_Attribute_Abstract $attribute
* @param string $bind attribute of the main entity to link with joined $filter
* @param string $filter primary key for the joined entity (entity_id default)
* @param string $joinType inner|left
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
joinAttribute($alias, $attribute, $bind, $filter=null, $joinType=’inner’, $storeId=null)

joinTable: joins table $table

Here are the parameters of the function joinTable:-

$table = table name to join
$bind = ( parent_key = foreign_key )
$fields = array of fields to select
$cond = where condition
$joinType = join type

/**
* Join a table
*
* @param string|array $table
* @param string $bind
* @param string|array $fields
* @param null|array $cond
* @param string $joinType
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
joinTable($table, $bind, $fields=null, $cond=null, $joinType=’inner’)

Using joinAttribute and joinTable

In the code below, all order invoice items are selected, i.e. all products that have been invoiced.
joinTable is used to join sales_order_entity table to fetch increment_id and store_id of the invoice for each product.
joinAttribute is used to fetch order_id, product_name, and store_id.
joinTable is used again to fetch the order status of each invoice item.

$collection = Mage::getModel('sales/order_invoice_item')
                    ->getCollection()
                    ->joinTable('sales_order_entity', 'entity_id=parent_id', array('invoice_id'=>'increment_id', 'store_id' => 'store_id'), null , 'left')
                    ->joinAttribute('order_id', 'invoice/order_id', 'parent_id', null, 'left')
                    ->joinAttribute('product_name', 'invoice_item/name', 'entity_id', null, 'left')
                    ->joinAttribute('store_id', 'invoice/store_id', 'parent_id', null, 'left')

                    ->joinTable('sales_order', 'entity_id=order_id', array('order_status'=>'status'), null , 'left')
                    ;
joinField: joins regular table field using an attribute as foreign key

/**
* Join regular table field and use an attribute as fk
*
* Examples:
* (‘country_name’, ‘directory/country_name’, ‘name’, ‘country_id=shipping_country’, “{{table}}.language_code=’en’”, ‘left’)
*
* @param string $alias ‘country_name’
* @param string $table ‘directory/country_name’
* @param string $field ‘name’
* @param string $bind ‘PK(country_id)=FK(shipping_country_id)’
* @param string|array $cond “{{table}}.language_code=’en’” OR array(‘language_code’=>’en’)
* @param string $joinType ‘left’
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
joinField($alias, $table, $field, $bind, $cond=null, $joinType=’inner’)

removeAttributeToSelect: removes $attribute from SELECT clause; specify null to remove all attributes

/**
* Remove an attribute from selection list
*
* @param string $attribute
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
removeAttributeToSelect($attribute=null)

setPage: sets LIMIT clause by specifying page number (one-indexed) and number of records per page; equivalent to calling setCurPage($pageNum) and setPageSize($pageSize)

/**
* Set collection page start and records to show
*
* @param integer $pageNum
* @param integer $pageSize
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
setPage($pageNum, $pageSize)

importFromArray: imports 2D array into collection as objects

/**
* Import 2D array into collection as objects
*
* If the imported items already exist, update the data for existing objects
*
* @param array $arr
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
importFromArray($arr)

exportToArray: returns collection data as a 2D array

/**
* Get collection data as a 2D array
*
* @return array
*/
exportToArray()

setOrder: alias for addAttributeToSort() q.v., identical except that it can accept array of attributes, and default $dir is desc

/**
* Set sorting order
*
* $attribute can also be an array of attributes
*
* @param string|array $attribute
* @param string $dir
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
setOrder($attribute, $dir=’desc’)