Magento debugging hints

If you are a web developer, there’s one thing you are doing from day to day, no matter how good you are. You can write a good code, and you may know your work like a pro, but usually you have to integrate your solutions into different systems which were, unfortunately, created by someone else. Here we meet the thing that can turn into the nightmare for you if you are following a wrong way – the debugging.

Let’s remember the days when we were able to output the debug data using the simple constructions like print_r(), var_dump(), var_export(), etc. and that completely met our requirements. In case of Magento, we are working with heavyweight constructions, so we need to investigate the effective ways to find the broken places or some intermediate values.

Fortunately, Magento has a lot of useful tools and methods to make the debugging process more handy and fast. In addition, you need to improve your development environment a bit, to make the way of debugging less painful. Xdebug – it is a great PHP extension for debugging and profiling. It allows you to set breakpoints in your code and stop PHP interpreter on these breakpoints for viewing application data on each executed line. Most of the popular IDEs, including NetBeans, PHPStorm, Eclipse, Aptana and others support xdebug integration. So it should not take a lot of time to install and configure the extension for most platforms. If you are using xdebug, you don’t have to use ‘echoing’ variables approach for the debug purposes anymore. It allows you to inspect Magento objects easier and faster.

Xdebug in action

Great, but let’s not forget about a hardcore. What are we going to do when we need to debug something on a remote system using only SSH and command line tools? People who worked with Zend Framework before, may know the answers. We have the useful class in ZF called Zend_Debug. It does not contain many methods, but you can find a function there, that works like a var_dump. The static method Zend_Debug::dump() prints or returns information about an expression:

Zend_Debug::dump($var, $label = null, $echo = true)

The $var argument specifies the expression or variable about which the method outputs information. The $label argument is a string to be prepended to the output. It may be useful, for example, to use the labels if you are dumping information about the multiple variables on a given screen. The $echo argument specifies whether the output of the method is echoed or not. Actually, this method – it’s nothing more than a wrapper for var_dump(). However, it extends var_dump() functionality a bit.

Ok, now we know how to output the debug info, but what if we have to make a debug on the environment which is working in the production mode, and if you break it somehow, the owner will head you off. We have a few ways to hide our debug activity in that case. First and fast – you can just restrict the debug info output by your IP. As a result, your piece of code will look something like this:

if ($_SERVER[‘REMOTE_ADDR’] == ‘69.69.69.69’) {
    Zend_Debug::dump($var, $label = null, $echo = true);
}

But, we have more intelligent way. Let’s use the logging system for our debugging purposes. Magento has a set of built-in methods to help to use logging for any info we want. To output some info into a log file you can use method Mage::log(). The method is declared into app/Mage.php itself and has 4 parameters:

public static function log($message, $level = null, $file = '', $forceLog = false)

The $message argument specifies the string to be outputted into a file. The second $level argument defines a debug message log level. There are 8 log levels available in Zend Framework and Magento:

const EMERG   = 0;  // Emergency: system is unusable
const ALERT   = 1;  // Alert: action must be taken immediately
const CRIT    = 2;  // Critical: critical conditions
const ERR     = 3;  // Error: error conditions
const WARN    = 4;  // Warning: warning conditions
const NOTICE  = 5;  // Notice: normal but significant condition
const INFO    = 6;  // Informational: informational messages
const DEBUG   = 7;  // Debug: debug messages

If null was specified as the parameters value – your debug message will threat as a DEBUG level message. You are able to use either integer value (0..7), or constants to make your code more readable (Zend_Log::EMERG, Zend_Log::NOTICE etc..).

The $file argument contains a relative path to the log file. Magento puts logs into the var/log directory, so if you pass a filename as a parameter you will find your file in this directory. $forceLog – it’s a very useful parameter since it allows you to use Mage::log even if the logging is disabled in the Magento config. For non-regular instant debugging just pass this parameter as true to be sure that your message will be logged regardless of magento config. The complete structure for logging a variable will look like the following one:

Mage::log(Zend_Debug::dump($product, null, false), null, ‘product_debug.log’, true);

We are using Zend_Debug::dump() for variable dumping, pass the third parameter as false to disable output. In that case, debug method returns the string which is being written into a log file. The log path is ‘product_debug.log’, so the file will be placed as a var/log/product_debug.log.

Also, you can use mageDebugBacktrace() function. This function allows you to get files call stack. It may be useful in your log files to see what goes after what.

Moreover, we have the log. Now is the time to investigate how we can view this log using command line tools without need to refresh the screen like a crazy. We have the great unix command line utility called tail. Go to the Magento log folder and open your log file via a tail using -f (or –follow) as a parameter:

cd var/log
tail product_debug.log -f

Now, you are able to see the file changes as they are appearing.

As you may already know, most of the Magento models are children of the parent class Varien_Object. This class has the useful method debug, which can help you to get model’s data in a readable format. For example, let’s try to debug a product’s model to get the current product’s data:

$product = Mage::getModel('catalog/product')->load(12);
Zend_Debug::dump($product->debug())

So, you’ll get all the products data values. You may ask, what’s the difference between Zend_Debug::dump($product->getData()) and this solution? It’s simple. If you try to debug with getData() call, you will get info about all object’s data items, and if some item is an object – you are getting a list of the object’s properties. On the other hand, if you are debugging using the debug() method and some data item is an object – you are getting only the object’s data without other unnecessary values for the debugging purposes in this case.

If you need to get class methods (for some reason, you need to do it on the remote environment using SSH, you have no IDE, and you are alone in the dark forest), here you can use the following construction:

Zend_Debug::dump(get_class_methods(get_class($product)))

The good news – this will help you to see a limited list of the object’s methods. The bad is – you can’t see methods arguments in such way (you have to get out from the forest and return to your IDE with xDebug installed).

If someday, you will open a live store page and see the blank page without any explanations – maybe, everything is not so bad. Open index.php in your Magento root directory and find the line with the following code:

#ini_set('display_errors', 1);

and surround it by your ip address, since we don’t want to show our fail to everyone:

if ($_SERVER[‘REMOTE_ADDR’] == ‘69.69.69.69’) {
    ini_set('display_errors', 1);
}

There’s a big chance that you will get the reason of your error and fix it quickly.  By the way, we would not recommend to rush to set Mage::setIsDeveloperMode(true) at this point, because that might cause additional troubles instead of helping you to fix a small issue.

It might be the situation, when you need to detect a *.phtml file on a remote server, and you have no time to dig in xml layouts and block classes. In that case, the template hints can help you greatly. Go to Admin->System->Configuration. In the upper part of the sidebar choose the necessary website in “Current Configuration Scope”. Then, on the same page find the tab called ‘Developer’ and in the section ‘Debug’ enable “Template Path Hints” and “Add Block Names to Hints” but STAY AWAY FROM SAVING at this step. If you don’t want to “improve” the site’s design like it’s being showed on the picture below, you need to restrict this option by your IP. On the same tab find the section “Developer Client Restrictions” and put your IP address there. Now, you can save the changes. If you have done everything correctly, you will see something like this:

Magento blocks hints enabled

Finally, if some extension has suddenly stopped working and nothing helps – do not be discouraged. Before, you will immerse yourself into a deep debugging, think like a person who might ‘broke’ the extension. Go to the Admin->System->Configuration->Advanced and ensure that the extension’s output isn’t disabled there. It happens so often :)