为什么我对Magento Block的getTemplateFile方法的调用返回null


Why is my Call to a Magento Block's getTemplateFile method returning null?

>当我在索引控制器中使用以下代码时

<?php
class Nofrills_Booklayout_IndexController  extends Mage_Core_Controller_Front_Action
{
    public function indexAction()
    {
        $block = new Mage_Core_Block_Template();        
        $block->setTemplate('helloworld.phtml');
        var_dump($block->getTemplateFile());
    }
}

我期待这样的结果

string 'frontend/base/default/template/helloworld.phtml' (length=47)

但是,在我的系统上,我得到

null

我的系统有什么问题,它返回null

调用
<code>getTemplateFile</code>

或者我如何自己调试?

发生在Magento 1.7.0.1上。

正如Vinai在他最初对OP的评论中所指出的那样,这个问题需要一个压缩包来排除故障。

必须加载Mage_Core_Block_Abstract的类定义,否则将输出有关include()或非对象操作的错误,或者根据开发人员模式可能根本没有输出。

应该注意的是,getTemplateFile()直到Magento 1.4.1.0才被定义。那么最有可能的问题是 Mage_Core_Block_TemplateMage_Core_Model_Design_Package 的版本不正确,无论是在本地或社区代码池中修改,还是报告的 Magento 版本不正确。有用的输出如下:

public function indexAction()
{
    ini_set('display_errors',1);
    Mage::setIsDeveloperMode(true);
    $block = new Mage_Core_Block_Template();
    $block->setTemplate('helloworld.phtml');
    $debug = new ReflectionClass($block);
    echo Mage::getVersion();
    Zend_Debug::dump($debug->getFileName());
    Zend_Debug::dump($debug->getMethods());
}

我对此进行了调查,但我无法在新安装的 1.7.0.1 版本上重现该问题。 这意味着您的系统配置有所不同。可能是文件权限的事情,可能是一些更改的Magento代码,可能是我没有考虑的事情。

这意味着弄清楚发生了什么的唯一方法是通过Magento如何确定模板的路径进行漫长的艰苦调试。 在正常的系统操作下,这将永远不会返回空值。 由于某种原因,在您的系统上确实如此。 我将在下面概述此类调用的正常调用堆栈。 希望这能为您提供使系统正常运行所需的信息。

此外,在我们进入调用堆栈之前,您的继承链和/或模板块方法可能已被搞砸。 null值是当调用Varien_Object的魔术设置器并且没有设置任何值时返回的值。 检查您的Mage_Core_Block_Template类是否仍然具有它getTemplateFile方法,以及

class Mage_Core_Block_Template extends Mage_Core_Block_Abstract
abstract class Mage_Core_Block_Abstract extends Varien_Object    

请记住,下面的文件路径假设没有人在您的系统上的某个地方放置类覆盖或重写

getTemplatefile方法在 中定义

#File: app/code/core/Mage/Core/Block/Template.php
public function getTemplateFile()
{
    $params = array('_relative'=>true);
    $area = $this->getArea();
    if ($area) {
        $params['_area'] = $area;
    }
    $templateName = Mage::getDesign()->getTemplateFilename($this->getTemplate(), $params);
    return $templateName;
}

您可以看到这是一个包装器,用于getTemplateFilename设计包对象。

#File: app/code/core/Mage/Core/Model/Design/Package.php
public function getTemplateFilename($file, array $params=array())
{
    $params['_type'] = 'template';
    return $this->getFilename($file, $params);
}

这反过来又是getFilename的包装

#File: app/code/core/Mage/Core/Model/Design/Package.php
public function getFilename($file, array $params)
{
    Varien_Profiler::start(__METHOD__);
    $this->updateParamDefaults($params);
    $result = $this->_fallback($file, $params, array(
        array(),
        array('_theme' => $this->getFallbackTheme()),
        array('_theme' => self::DEFAULT_THEME),
    ));
    Varien_Profiler::stop(__METHOD__);
    return $result;
}

反过来,这是对_fallback的呼吁

#File: app/code/core/Mage/Core/Model/Design/Package.php
protected function _fallback($file, array &$params, array $fallbackScheme = array(array()))
{
    if ($this->_shouldFallback) {
        foreach ($fallbackScheme as $try) {
            $params = array_merge($params, $try);
            $filename = $this->validateFile($file, $params);
            if ($filename) {
                return $filename;
            }
        }
        $params['_package'] = self::BASE_PACKAGE;
        $params['_theme']   = self::DEFAULT_THEME;
    }
    return $this->_renderFilename($file, $params);
}

_fallback method also calls the validateFile_renderFilename方法。

#File: app/code/core/Mage/Core/Model/Design/Package.php    
public function validateFile($file, array $params)
{
    $fileName = $this->_renderFilename($file, $params);
    $testFile = (empty($params['_relative']) ? '' : Mage::getBaseDir('design') . DS) . $fileName;
    if (!file_exists($testFile)) {
        return false;
    }
    return $fileName;
}
...
protected function _renderFilename($file, array $params)
{
    switch ($params['_type']) {
        case 'skin':
            $dir = $this->getSkinBaseDir($params);
            break;
        case 'locale':
            $dir = $this->getLocaleBasedir($params);
            break;
        default:
            $dir = $this->getBaseDir($params);
            break;
    }
    return $dir . DS . $file;
}    

沿着这条路径的某个地方,您的 null入到混合中。

(如果您最终找到答案,请告诉我们)