Occasionally I've needed to take a closer look at exactly which block, layout or config file is being loaded by Magento. In this post I will demonstrate a "brute force" approach to checking exactly what is being processed.

Please note: Where possible, we will be using Magento's logging, the output of which will be written to the file var/log/system.log, which also includes the rest of the system logging output. Logging must be enabled for output to be written to this file - you can enable logging in the Magento admin panel by going to System → Configuration → Developer → Log Settings and setting Enabled to True.

Blocks

  • The getBlockClassName() function in app/code/core/Mage/Core/Model/Config.php is responsible for translating block paths (i.e. adminhtml/sales_order) into a filename (i.e. app/code/core/Mage/Adminhtml/Block/Sales/Order/Grid.php or a custom block such as app/code/local/Fontis/CustomModule/Block/Adminhtml/Sales/Order/Grid.php). To see which block paths are getting mapped to which class files, add a logging statement:

    public function getBlockClassName($blockType)
    {
     if (strpos($blockType, '/')===false) {
     return $blockType;
     }
    
     // added log statement below
     Mage::log("$blockType mapped to ".$this->getGroupedClassName('block', $blockType));
     
     return $this->getGroupedClassName('block', $blockType);
    }
    

  • The _getBlockInstance() function in app/code/core/Mage/Core/Model/Layout.php takes a block path or class name and finds the corresponding PHP file to load. Add some logging to this and you can see exactly what's getting loaded. (New lines are $orig = $block and Mage::log(...).)

    protected function _getBlockInstance($block, array $attributes=array())
    {
     // added line below
     $orig = $block;
     
     if (is_string($block)) {
     if (strpos($block, '/')!==false) {
     if (!$block = Mage::getConfig()->getBlockClassName($block)) {
     Mage::throwException(Mage::helper('core')->__('Invalid block type: %s', $block));
     }
     }
     $fileName = mageFindClassFile($block);
     if ($fileName!==false) {
     
     // added log statement below
     Mage::log("_getBlockInstance: $orig -> $fileName");
     
     include_once ($fileName);
     $block = new $block($attributes);
     }
     }
     if (!$block instanceof Mage_Core_Block_Abstract) {
     Mage::throwException(Mage::helper('core')->__('Invalid block type: %s', $block));
     }
     return $block;
    }
    

Layouts

  • The fetchFileLayoutUpdates() function in app/code/core/Mage/Core/Model/Layout/Update.php is where the XML layout files get loaded. Insert a logging statement to see what's getting processed

    public function fetchFileLayoutUpdates()
    {
     // ...some lines omitted here...
    
     foreach ($updateFiles as $file) {
     $filename = $design->getLayoutFilename($file);
     Mage::log("Loading layout file $filename");
     if (!is_readable($filename)) {
     continue;
     }
    
     // added logging statement below
     Mage::log("Loading layout file $filename");
    
     $fileStr = file_get_contents($filename);
     $fileStr = str_replace($this->_subst['from'], $this->_subst['to'], $fileStr);
     $fileXml = simplexml_load_string($fileStr, $elementClass);
     if (!$fileXml instanceof SimpleXMLElement) {
     continue;
     }
     $layoutStr .= $fileXml->innerXml();
    
     #$layoutXml->appendChild($fileXml);
     }
    
     // ...some lines omitted here...
    }
    

Configuration

  • The loadFile() function in lib/Varien/Simplexml/Config.php is what actually loads config XML files. Adding some logging statements in here will show you exactly which XML files are getting loaded, but as it's executed before the built-in Magento logging functionality, we need to use a more basic method. (New lines are between fopen() and fclose() inclusive - remember to change the path to something that makes sense for you.)

    public function loadFile($filePath)
    {
     if (!is_readable($filePath)) {
     //throw new Exception('Can not read xml file '.$filePath);
     return false;
     }
    
     // new lines added below
     $log = fopen("/var/www/magento/var/log/xml.log", "a");
     fwrite($log, "Loading XML file: $filePath\n");
     fclose($log);
     // end of new lines
    
     $fileData = file_get_contents($filePath);
     $fileData = $this->processFileData($fileData);
     return $this->loadString($fileData, $this->_elementClass);
    }
    

Instrumenting the core code with logging statements is certainly a down and dirty approach, but sometimes it's useful to check exactly what's getting loaded without going to the effort of firing up a debugger.