Data in Magento is handled in a very organized, and for the most part, efficient manner. Knowing how data is accessed and displayed can be a little daunting for a newcomer to Magento. In this blog post, I’ll attempt to clear up some of the main areas concerning data in Magento.
Order of Products
There are a number of ways in which products can be ordered on a Magento category page. The default options are “Name“, “Best Value“, and “Price“.
Name – displays the products by alphabetical order
Price – displays them by ascending price value (cheapest to most expensive).
Best Value – allows the admin user determine the order in which the products are shown
This uses an attribute named Position, which can be found by navigating to Catalog->Categories->Manage Categories in the backend, clicking selecting a category and then selecting the Category Products tab. This will show all of the products associated with that category as well as the position attribute and its value. By default the value is zero, and the higher the number on a product, the farther down the list it will appear when being ordered on the frontend. Otherwise, if you are using a custom collection and no order is being set, the product collection will be ordered by the price ID.
If you find yourself needing to add an order to a custom collection, for instance using name, you can simply call setOrder() on the collection before you step through it, specifying the attribute code and the direction (ascending, descending). For example:
Simple. You may find yourself, in some cases calling addAttributeToFilter(“attribute_code”), for an attribute that is not included in a collection model, which painlessly makes any extra attributes available to you within the collection. However, there are rare occasions when just doing this will not work.
The following is an example of when I had to order a product collection by three attributes that were not included in the product collection model – Stock Quantity, Is In Stock, and a custom int attribute:
->join('catalog_product_entity_int AS cat_int','cat_int.entity_id=e.entity_id AND cat_int.attribute_id=181 AND cat_int.store_id = 0','value')
->join('cataloginventory_stock_item AS cat_stock','cat_stock.product_id=e.entity_id','qty')
->join('cataloginventory_stock_item AS cat_stock_avail','cat_stock_avail.product_id=e.entity_id','is_in_stock')
As you can see, the setOrder() method would not work in this instance, and I was forced to reset the order on the select object by using getSelect()->reset(Zend_Db_Select::ORDER). Then the three joins for each of the attribute I wanted to add to the collection, and then calling order() – which takes the same parameters as setOrder() – for each of the attributes I wanted to order by.
TIP: If you’re ever debuggin in moments like this and you want to read the select object being created, or you want to test it on a db, you can assign it as a string using:
$select = (string) $collection->getSelect();
The layered nav is a vital part in helping customers navigate through products on your site. The layered nav pulls any categories and attributes that the currently displayed collection of products is associated with, allowing the customer to filter the collection down to only the products that are associated with the attributes and/or categories that they desire. The attributes can be displayed with, or without results. This can all be controlled at Catalog->Attributes->Manage Attributes in the backend, and then by creating an attribute or selecting an existing one. The only drawback to magento’s native layered nav set up is that only attributes that are of type “dropdown” can be selected to show up in the layered nav, however, this is really the most sensible and organized way of doing this.
Magento does not really need to be tampered with, and I wouldn’t recommend doing so, however, some requests have come up for allowing the customer to be able to filter by multiple values of the same attribute. The way the layered nav works by default is that when a specific value is selected from an attribute, you can no longer filter by the attribute. This is the clean safe way of doing it, however there are extensions which allow you to filter multiple times by the same attribute, for instance Mana Filters. Again, if you do not have to do this, don’t bother as making changes like this can just cause problems in the long run.
Magento search out of box, is functional, but not ideal. Especially not for very large catalogs. The Magento configuration can be found at System->Configuration in the backend, then by selecting catalog, in the left nav, and then by expanding the Catalog Search tab. Magento’s default search engine is MySql Fulltext, and has three types: Like, Fulltext, and a combination of the two. Like is the better for generic searches but often I find that the search will not display the most desired results and at times will show very strange or unexpected results. Fulltext is really only good for a very specific searches, although it does also show unexpected results at times. The option that is a combination of the two is at most times, the best search type to go with.
From the attribute management page, attributes can be selected to be included in search, which will allow customers to search for skus, authors, etc. from the search bar. Keep in mind though, that this only works ideally if the attribute you are searching has much different values than the title of the product. For instance, if the customer are searching for a books by Charles Dickens and the catalog contains 200 products with “Dickens” just in the title, then the products with “Dickens” in the title are going to show up before any products that just have an author value containing “Dickens”.
The other search Magento supports is Solr, which is inarguably the superior of the two. Its much more advanced and boasts more accurate results, however, it takes a little extra effor to set up. A detailed walkthrough can be found here.
The product page is where the customer goes to see the meat of the product information, but its important not to clutter the page with any uneccessary data. Attributes such as brand, author, etc. are most often added under the title but adding too many attributes on the main page clutters the look and are uneccessary. Many attributes are displayed in the collateral below the product image/price info, including the description, and an attribute grid. Once again, attributes can be chosen to show up on the product page by going to Catalog->Attributes->Manage Attributes in the backend. An attribute value – for instance “Brand” can then be displayed on the product page by echoing:
where “brand” is the attribute code. If the attribute code was “brand_name” you would use:
If the attribute in question is dropdown, the code would look like:
If for whatever reason you want to display the value of an attribute without adding the attribute to show up on the front end, you can access all the attributes of that product by loading the product model:
$_product_model = Mage::getModel("catalog/product")->load($_product->getId());
This is not always the best solution though, as it can be heavy loading the model, especially if you are looping through a collection of products and loading the model every time.
Magento layouts are extremely useful and are very powerful for controlling what you display on a given page. Best practise would be to create a local.xml file within your custom theme and include any layout changes you need to make in there. That way all of your changes are in one place, and will override any other layout file in magento. For instance if you want to remove the breadcrumbs on a cms page this can be done by entering:
Adding a block can be done by adding a simple call of:
<block type=”newsletter/subscriber” name=”newsletter” as=”newsletter” before=”-” template=”newsletter/subscriber.phtml” />
In the block call, “type” is the block class, in which this one is referencing “Newsletter/Block/Subscribe.php”, “name” and “as” are for referencing the block from other files, and “template” is the path to the actual template file. In the “before” value, you can specify a block name that you would like the block to appear before, and the same can be done by including an “after” value. leaving the value as “-” means that the block will appear before or after all other blocks within that reference level.
However, you can omit the before or after tag, and instead choose where the block will show up by including getChildHtml(“block_name”) ?> in the template of the reference the block is contained within.