Get All Sale Products From A Category in Magento

I recently was tasked with creating a landing page that took all the products that were on sale in a particular category. At first this seemed like a challenge because I was not sure how to get a collection of products from a particular category.

What I discovered that you can do is load a category model and then get a product collection and then continue to filter it down until you have the products that you are looking for. Here is the code that I used to achieve this:

$products = Mage::getModel('catalog/category')->load($category_id)
 ->addAttributeToFilter('status', 1)
 ->addAttributeToFilter('visibility', 4)
 ->addAttributeToFilter('special_price', array('neq' => ""))
 ->setOrder('price', 'ASC')

What you will notice is that instead of loading a catalog/product, I loaded a catalog/category model. From there I got a product collection and then I put in some standard filters (only show products that have the proper visibility, are enabled, and whose special_price attribute does not equal blank. Finally I set the sort order to be the products price.

Overall this was very simple once I realized that I had to use the category model.

When Reindexing in Magento Fails, Use The Command Line

One of the things that you have to get used to when running Magento is dealing with the indexes that it relies on. Usually you can do this from the admin panel by going to System -> Index Management.

When indexing fails from the admin panel you get a message saying that it failed with no reason why it failed. Now in most cases you cannot ignore this. You may find that most (if not all) of your products has disappeared from the front end of the website.

While I am not entirely sure of the cause of the re-indexing failing, the one way I have discovered how to successfully re-index is to turn off your web server and run a special command line script to do your re-indexing. Not only does this almost always complete, but if it does fail it will give you an error message (I have only ever seen it give an Integrity Constraint Violation).

The command line script is located in the shell/ directory of your Magento install. The script is called indexer.php and there are a number of options you can use to do just about anything you could with the admin panel.

I would recommend playing around with on a development server so that you can become familiar with how it works so when you are ready to use it when it is crunch time.

Some Common Uses

php indexer.php                   - Displays help information on how to use the script
php indexer.php --status          - Shows the status of all the indexes
php indexer.php info              - Shows the "codes" for the individual indexes
php indexer.php --reindex <code>  - Re-indexes the <code> index
php indexer.php reindexall        - Re-indexes all the indexes

Set All Your Magento Categories to is_anchor

I recently was tasked to set every category inside our Magento installation have its is_anchor attribute set to true. We have over 600 categories so it would be a huge task to do this by hand so I put together a quick script that did this in less than a minute.

ini_set(‘display_errors’, ‘1’);

// Load Up Magento Core
define(‘MAGENTO’, realpath(‘/path/to/magento’));

require_once(MAGENTO . ‘/app/Mage.php’);

$app = Mage::app();

$categories = Mage::getModel(‘catalog/category’)
->addAttributeToFilter(‘is_anchor’, 0)
->addAttributeToFilter(‘entity_id’, array("gt" =&gt; 1))

foreach($categories as $category) {
echo $category-&gt;getId() . "\t" . $category->getName() . "\n";

The first thing I did was pull in Magento’s functionality so I could load up a collection of categories. You will notice that I only got categories that had their is_anchor property set to 0 and an entity_id greater than 1.

From there I did a foreach on all the categories and set the category is_anchor property to 1 and saved it. I decided to echo out the category name so I could watch the script process the categories.

Give Your Command Line Script Full Access to Magento

In the past year, I have had the pleasure of having to write a lot of scripts that accomplish certain tasks inside Magento. It is not immediately obvious how to do this, but once you know how, you will love the power that it gives you.

In your PHP script simply put the following at the top:
ini_set(‘display_errors’, ‘1’);

// Load Up Magento Core
define(‘MAGENTO’, realpath(‘/path/to/magento’));

require_once(MAGENTO . ‘/app/Mage.php’);

$app = Mage::app();


You can now do anything you would normally do inside Magento. I usually end up loading and manipulating a models in my scripts. You will notice at the top that I set error reporting to be outputted. I like to do this to ensure that errors are being displayed on the command line (it will override any other settings).

Using jQuery Listnav Plugin

Yesterday I was looking around for a creative way to display what will eventually become a very large list of information. Generally I would just use extra links and sort them alphabetically. For me it had never seen like the most ideal solution. Forcing the user to wait while the page reloads itself is actually a bad solution. What if you could just have all the information load once and the user could then instantly browse all that information?

This is how I came across the jQuery ListNav Plugin by iHwy. It does exactly what I was looking for. It takes a large list of information and makes it very easy to work with.

All you have to do is place the location you want the navigation bar to go, then you create your unordered list, and then just put in a single jQuery command and it does the rest. It could not be simplier.

I have so many different ideas where this could be used. The one I probably see is creating an interactive product listing for an eCommerce site. Many websites make HTML versions of their sitemaps for SEO rankings. These pages generally have little to no use for the end customer because it usually is just a bunch of links displayed. With this plugin, you really could make this information useable by customers. A very neat concept.

You can view the demo of the plugin in action here. You can also view how I used this on another one of my websites by clicking here.

Creating a jQueryUI Accordian

An accordion is the ideal choice for when you have to put a lot of information on the screen, but you do not have a lot of screen real estate available for that information.

Luckily for us we can create an accordion very easily using jQueryUI.

First thing you need to do is place all of your information inside your HTML like this:

<div id="accordion">
	<a href="#">First Section Title</a>
	<div>First Section's Content would be placed inside of this div</div>

	<a href="#">Second Section Title</a>
	<div>First Section's Content would be placed inside of this div</div>

	.... Repeat this for as many sections you want ....


Now that you have your HTML structure set up, now all you have to do is use some Javascript to tell jQuery UI to turn it into a the accordion.

<script type="text/javascript">
		$('.accordion .head').click(function() {
			return false;

Now you have a very easy way to put a large amount of information inside of a limited space.

PHP Function – str_replace

The str_replace function is used to replace part of a string with another string. The syntax of this PHP function is detailed below:

mixed str_replace( $search, $replace, $subject, $count );

$search – This can either be a string value or an array of strings. This will be the string or strings you want to be replaced.

$replace – This can either be a string or an array of strings. These will be the value that is replaced when one of the $search items are found.

$subject – The string that will be searched and have replacements placed inside of it.

$count (optional) – The maximum number of times a replace should occur.

There are a number of reasons why you would want to use this function. One of the ways that I use str_replace is when I need to remove line breaks from the a large string that you are working with. You would do that by doing the following:

$input = str_replace( "\n", '', $input );

You may have noticed that I used $input as the return variable and the string that is having the replace performed on it. This is a quirk that I use in order to not have to create extra variables and you cannot pass the $input to the function as reference.

PHP Boolean Type

The boolean data type in PHP is very easy to use (and why should it be difficult, it is either True or it is False).

The basic way to set a boolean value is to use the true and false keyword. Unlike other programming languages, true and false are case insensitive so you can either use true, True, TrUe, or any other variation to get the same effect.

For example:

$yes = true;
$yes2 = True;

$no = false;
$no2 = False;

These are all valid ways to set a variable to true or false.

PHP has some interesting ways of determining if a variable is true or false. Since PHP is a dynamically typed language, nearly any type can be evaluated as true or false. The way you can keep this straight in your head is if the variable’s value is at its default state, it will likely be evaluated as false.

To be more official, here is how PHP evaluates true or false from various values:

  • the boolean FALSE itself
  • the integer 0 (zero)
  • the float 0.0 (zero)
  • the empty string, and the string “0”
  • an array with zero elements
  • an object with zero member variables (PHP 4 only)
  • the special type NULL (including unset variables)
  • SimpleXML objects created from empty tags

Text taken from PHP manual at:

Use cURL to Connect To Another System

cURL is a very useful tool used to pragmatically connect and interact with other systems to do various tasks like download a Web Page or RSS feed. It is also used to send information to another computer and get a response. A common example of using cURL is when you are purchasing something online. When you get your shipping quote or authorizing your credit card, you are very likely using something like cURL.

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
$result = curl_exec ($ch);

These 5 lines of code do a lot. In line 1 you begin creating your transaction by calling curl_init() and passing the URL you want to connect to (in this case we have a variable called $url).

Lines 2-4 set different options for the transaction. The CURLOPT_HEADER option is set to zero to signify we do not want the header information in the response. CURLOPT_RETURNTRANSFER tells cURL to assign the data we receive to a variable rather than simply output it to the screen. CURLOPT_POSTFIELDS sets what data we want to send in the header of our request. This is a very important option when interacting with other systems as this is generally where you will put your XML or other header data that is required by the system you are connecting with.

Line 5 actually executes the request. It will reach out to the $url, with $fields in the POST areas of variables and putting the data we received into the variable $result. With this variable you can do whatever you need in order to make your application work.

The Ultimate PHP CSV Parser

Lately I have been trying to find cool PHP utilities that I can use to handle my day to day tasks. Lately parsing CSV files in PHP has been something I have had to do over and over again. Such a basic task can be such a pain considering all of the different formats that they can be in (mostly the quotes around some of the values). I would do find and replace on the file to remove all the extra stuff and hope that I did not corrupt the data.

There had to be a better way to do this. I did some searching and I found Ming Hong Ng’s CSV Parsing class. It worked perfectly. I have parsed a ton of CSV files with no problems at all. You can download this class from:

It is so simple to use too! Simply create an instance and call ParseFromFile or ParseFromString. The data is stored in the data instance variable. So simple!

This is something that should be apart of any PHP programmers toolkit.