Categories


Archives


Recent Posts


Categories


Symlinks with Templates in CE 1.6

astorm

Frustrated by Magento? Then you’ll love Commerce Bug, the must have debugging extension for anyone using Magento. Whether you’re just starting out or you’re a seasoned pro, Commerce Bug will save you and your team hours everyday. Grab a copy and start working with Magento instead of against it.

Updated for Magento 2! No Frills Magento Layout is the only Magento front end book you'll ever need. Get your copy today!

Magento Version: 1.6.rc1+

I just downloaded the release candidate for Magento 1.6, and I noticed a change that seemed like a regression, but a little digging made me realize it was something else.

A lot of Magento developers (meaning me) like keeping their custom phtml files somewhere other than the the standard add/design/frontend file hierarchy. They accomplish this though symlinks, or by creating custom block objects that look elsewhere for the files.

However, in the 1.4 branch of community edition, this changed. Before rendering a block template, Magento started checking if the phtml file was located in the view directory, and they used PHP’s realpath function to normalize the directory string.

File: app/code/core/Mage/Core/Block/Template.php
...
$includeFilePath = realpath($this->_viewDir . DS . $fileName);
if (strpos($includeFilePath, realpath($this->_viewDir)) === 0) {
...

No more symlinks. You could still redefine fetchView in your own blocks to take this into account and store your files elsewhere, which I did.

In the 1.5 branch, this code was altered slightly.

if (strpos($includeFilePath, realpath($this->_viewDir)) === 0 || $this->_getAllowSymlinks()) {

The _getAllowSymlinks method

const XML_PATH_TEMPLATE_ALLOW_SYMLINK       = 'dev/template/allow_symlink';     
protected function _getAllowSymlinks()
{
    if (is_null($this->_allowSymlinks)) {
        $this->_allowSymlinks = Mage::getStoreConfigFlag(self::XML_PATH_TEMPLATE_ALLOW_SYMLINK);
    }
    return $this->_allowSymlinks;
}

checks for a config flag, and if it’s true allows the template file to render from a symlinked path. Yay for symlinks.

Turns out Magento 1.6 takes this a step further, and add the same check to setScriptPath

public function setScriptPath($dir)
{
    $scriptPath = realpath($dir);
    if (strpos($scriptPath, realpath(Mage::getBaseDir('design'))) === 0 || $this->_getAllowSymlinks()) {
        $this->_viewDir = $dir;
    } else {
        Mage::log('Not valid script path:' . $dir, Zend_Log::CRIT, null, null, true);
    }
    return $this;
}

This is what was tripping me up, even with an overridden fetchView, this check would stop my templates from rendering in app/code/pool/Package/Module.

Flipping this config bit at

System -> Configuration -> Developer -> Template Settings 

or redefining _getAllowSymlinks in your own blocks

protected function _getAllowSymlinks()
{
    return true;
}

should take care of this. That said, there’s probably a reason the core team wants to discourage template use outside of the approved directory, and it’s making me re-consider my placement of templates.

Here’s looking forward to Magento 2, where frontend files will be packaged up along with code modules!

Copyright © Alan Storm 1975 – 2019 All Rights Reserved

Originally Posted: 2nd July 2011