在 Magento 2 的 templates 中使用 $block
还是 $this
?
结论:$block
和 $this
指向同一个 block 对象,但是建议使用 $block
不建议使用 $this
。
在 M2 的 template 中,$this
指向的不再是该 template 的 block 对象,而是一个 template 类:Magento\Framework\View\TemplateEngine\Php
以之前的 ThankIT_HelloWorld 模块为基础,修改以下文件,进行实验。
File:app\code\ThankIT\HelloWorld\view\frontend\templates\index\index.phtml
Welcome to hellomagento2.com
<?php
echo '<br/>';
echo get_class($this);
echo '<br/>';
echo $block->sayHello();
echo '<br/>';
// discouraged
echo $this->sayHello();
File: app\code\ThankIT\HelloWorld\Block\Index\Index.php
<?php
namespace ThankIT\HelloWorld\Block\Index;
use Magento\Framework\View\Element\Template;
class Index extends Template
{
# ... other code
public function sayHello()
{
return __('Hello World');
}
#... ohter code ...
那么访问我们的 url http://example.com/helloworld/index/index/
得到的类名正是 Magento\Framework\View\TemplateEngine\Php
查看该类的以下方法:
/**
* Redirects methods calls to the current block
*
* This is needed because the templates are included in the context of this engine
* rather than in the context of the block.
*
* @param string $method
* @param array $args
* @return mixed
*/
public function __call($method, $args)
{
return call_user_func_array([$this->_currentBlock, $method], $args);
}
这就解释了为什么我们可以通过 $this
来调用 block 中的方法。
查看该类的以下方法
/**
* Render output
*
* Include the named PHTML template using the given block as the $this
* reference, though only public methods will be accessible.
*
* @param BlockInterface $block
* @param string $fileName
* @param array $dictionary
* @return string
* @throws \Exception
*/
public function render(BlockInterface $block, $fileName, array $dictionary = [])
{
ob_start();
try {
$tmpBlock = $this->_currentBlock;
$this->_currentBlock = $block;
extract($dictionary, EXTR_SKIP);
include $fileName;
$this->_currentBlock = $tmpBlock;
} catch (\Exception $exception) {
ob_end_clean();
throw $exception;
}
/** Get output buffer. */
$output = ob_get_clean();
return $output;
}
在 include $fileName;
前,$this->_currentBlock = $block
,而在 template 中,$block
和 $this->_currentBlock
是一样的。这就解释了为什么我们可以通过 $block
来访问 block 中的方法。
但是 The php sniffer with the EcgM2 standards
不建议使用 $this
,所以我们还是用 $block
吧。