Block类必须继承\Magento\Framework\View\Element\AbstractBlock,而\Magento\Framework\View\Element\AbstractBlock类又实现了\Magento\Framework\View\Element\BlockInterface。鉴于大多数Blocks需要渲染模版,所以大多数情况下他们在继承链中更进一步,继承自\Magento\Framework\View\Element\Template。
Blocks的问题
虽然Blocks可以很好的完成他们的工作,他们也有一些缺点。
所有的Blocks都使用构造注入,所以当一个Block需要额外的依赖的时候,它必须把依赖上下文变量传入parent::__construct()方法。
自然,许多开发人员然后通过受保护的getter或受保护的字段访问父项依赖项。这些定制逻辑和平台代码的交织导致代码更加复杂。 与简单的没有继承关系的类相比,代码变得难以理解和维护。
另外,当使用测试来驱动开发时,虽然依赖关系跟业务逻辑没有任何关系,但是因为必须处理父类之间的关系,使过程变得十分繁琐。 这是开发人员踏上TDD旅程的又一个障碍,并助长了难以进行测试的神话。
PHP视图模型 在写这编文章的时候我发现了以下模版block类上面的PHPDoc注释。
/** * Avoid extending this class. *
* If you need custom presentation logic in your blocks, use this class as block, and declare
* custom view models in block arguments in layout handle file.
* * Example: * * * My\Module\ViewModel\Custom\ *
* **/
此注释已添加到2.2版本中,并准确描述了Anton所指的内容。
更好的是,自Magento 2.2.1版本,我们甚至不用指定的class参数,因为 class="Magento\Framework\View\Element\Template" 是默认值。
现在我大多使用以下方式来声明我的Blocks, Example\ViewModel\Block\Example
<referenceContainer name="columns.top">
<block name="view-model-example" template="Example_ViewModel::example.phtml">
<arguments>
<argument name="view_model" xsi:type="object">Example\ViewModel\Block\Example</argument>
</arguments>
</block>
</referenceContainer>
模版是这样开始的:
<?php declare(strict_types=1);
/** @var \Example\ViewModel\Block\Example $viewModel */
$viewModel = $block->getData('view_model');
?>
<?php $viewModel->getSomeThing() ?>
这个视图模块必须实现标记接口,否则我们会遇到一个异常:
(UnexpectedValueException): Instance of Magento\Framework\View\Element\Block\ArgumentInterface is expected, got Example\ViewModel\Block\Example instead.
这个是异常中所指的ArgumentInterface
/** * Block argument interface.
* All objects that are injected to block arguments should implement this interface.
*/
interface ArgumentInterface { }
此限制是安全预防措施,由于布局可以在多个文件内配置--包括后台由商户添加的布局--此限制被用来限制由布局声明实例化Blocks的个数。
实际上,必须实现此接口并不是真正的麻烦。 我喜欢使用几乎解耦的视图模型,而不是从AbstractBlock扩展的块。
构造函数不需要调用 parent::__construct(),任何依赖关系都显而易见
在某些情况下,仍然需要使用自定义块。 例如,根据条件判断对模版进行渲染。 但是在大多数情况下,视图模型已经足够了。
视图模型的好处
简而言之,使用视图模型代替块可以更好地分离自定义代码和平台代码,这导致代码具有以下属性:
更容易理解
更易于维护
更可重用
更安全的升级
更容易测试
来源:oschina
链接:https://my.oschina.net/u/3623541/blog/3162855