系统学习magento二次开发,推荐小册:《Magento中文全栈二次开发 》
本小册面向Magento2以上版本,书代码及示例兼容magento2.0-2.4版本。涵盖了magento前端开发,后端开发,magento2主题,magento2重写,magento2 layout,magento2控制器,magento2 block等相关内容,带领您成为magento开发技术专家。
Magento / Adobe Commerce是一家知名的电子商务平台,拥有超过10年的业绩记录。从Magento 1的第一个版本到Magento 2的最新版本,它的主要优势是开箱即用的自动化业务流程的数量:目录,销售和营销,以及其他众多功能。为了确保组件之间的灵活通信并提供高效定制的能力,Magento 2开发了一种基于设计模式组合的复杂架构。
我们很高兴介绍一系列专门介绍Magento 2架构设计模式的文章。解释它们在电子商务平台架构中的作用不仅有助于理解Magento 2网站设计,而且还将对开发新的业务组件产生有益的影响。
在描述特定模式时,我们将使用以下结构:它的基本解释,在Magento / Adobe Commerce中的作用,最有效的模式的适用性和使用限制。这种结构应该有助于清楚地了解体系结构。
这篇文章是为谁写的?
我们在这些文章中介绍的材料适用于各种专业知识水平的开发人员,解决方案架构师以及想要了解有关Magento / Adobe Commerce设计的更多详细信息的人员。
对象管理器
概述
首先,我们决定描述对象管理器,因为它在Magento 2 / Adobe Commerce的大多数方面都起着主导作用。根据官方文档,对象管理器负责:
在工厂和代理中创建对象。
通过在请求时返回类的相同共享实例来实现单一实例模式。
通过在构造函数请求其接口时实例化首选类进行依赖项管理。
自动实例化类构造函数中的参数。
让我们通过检查作为Magento框架一部分的ObjectMagerInterface来更详细地查看此列表。这是描述其方法的最佳方式,因为方法实现是不言自明的。
方法创建
我们在界面中找到的第一种方法是创建。
/** * Create new object instance * * @param string $type * @param array $arguments * @return mixed */ public function create($type, array $arguments = []);
这种方法是常用的方法之一。在它的帮助下,对象管理器基于两个参数创建新对象:类型和参数。第一个是包含对象类型名称的字符串类型值。例如,Magento\Framework\Cache\Frontend\Adapter\Zend。 第二个带有 array 类型的参数包含对象的新实例所需的参数列表。
但是新对象初始化使用什么机制呢?我们认为耐心的读者已经对这个问题有了答案。在后台,对象管理器使用工厂方法模式按其类型生成新实例。
/** * Create new object instance * * @param string $type * @param array $arguments * @return mixed */ public function create($type, array $arguments = []) { return $this->_factory->create($this->_config->getPreference($type), $arguments); }
我们将在下一篇文章中回顾工厂方法,但现在让我们将其描述限制为几句话。在对象管理器的实现中,如果发送了$type参数,工厂会使用它来标识接口的首选项。在其他情况下,将直接生成类。这可以在 Config 类 getPreference 方法中看到。这是一个非常重要的部分,因为它描述了Magento 2 / Adobe Commerce中使用的依赖注入方法的强大功能。我们将在接下来的文章中更详细地回顾这一点。
方法获取
对象管理器接口中表示的另一种方法是 get 方法。这个平台与前面描述的平台具有相同的高价值。根据其声明,get 方法检索缓存的对象实例。
/** * Retrieve cached object instance * * @param string $type * @return mixed */ public function get($type);
通过此方法,对象管理器提供了对象生活方式配置的重要组成部分。根据它,某些类型的对象可以共享或不共享。换句话说,是单例或瞬态。在 di.xml 中,共享参数负责此配置:
<argument xsi:type="object" shared="{shared}">{typeName}</argument>
此方法的实现易于理解:
/** * Retrieve cached object instance * * @param string $type * @return mixed */ public function get($type) { $type = ltrim($type, '\\'); $type = $this->_config->getPreference($type); if (!isset($this->_sharedInstances[$type])) { $this->_sharedInstances[$type] = $this->_factory->create($type); } return $this->_sharedInstances[$type]; }
通过$type ObjectManger 类标识接口的首选项(如果已声明),如果对象存在于以前生成的(共享)对象的拉取中,则返回对象的缓存实例。
方法配置
列表中的最后一个,但第一个由平台调用。它的声明很简单:
/** * Configure object manager * * @param array $configuration * @return void */ public function configure(array $configuration);
随着实施
/** * Configure di instance * Note: All arguments should be pre-processed (sort order, translations, etc) before passing to method configure. * * @param array $configuration * @return void */ public function configure(array $configuration) { $this->_config->extend($configuration); }
此方法是 HTTP 调用和区域初始化期间整个应用程序初始化的入口点。在此步骤中,对象管理器致力于将 di.xml 中描述的所有首选项“收集”到一个地方 - 全局配置。
对象管理器用法
直接呼叫
谈论用法并开始有限制的解释可能听起来很奇怪,但它是完全有意义的。对象管理器在应用程序中的直接使用是危险的,因为它打破了基于类型和对象参数声明生成原子对象的想法。请记住,对象管理器实现中的 create 方法使用工厂方法,该方法的来源只需要对象名称(类型)。
工厂和代理
工厂和代理是直接调用对象管理器的某些例外,因为它们需要对象管理器来生成新对象。例如,您可以概述任何类型的 DTO 工厂。
向后兼容性
有时需要向对象构造函数添加新参数,并遵循向后兼容性规则,必须在对象管理器的帮助下声明新添加的对象。例如
<a href="https://github.com/magento/magento2/blob/2.4/app/code/Magento/Catalog/Model/Indexer/Category/Product/AbstractAction.php" target="_blank" rel="noreferrer noopener">Magento\Catalog\Model\Indexer\Category\Product\AbstractAction</a>
/** * @param ResourceConnection $resource * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Catalog\Model\Config $config * @param QueryGenerator $queryGenerator * @param MetadataPool|null $metadataPool * @param TableMaintainer|null $tableMaintainer */ public function __construct( \Magento\Framework\App\ResourceConnection $resource, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Catalog\Model\Config $config, QueryGenerator $queryGenerator = null, MetadataPool $metadataPool = null, TableMaintainer $tableMaintainer = null ) { $this->resource = $resource; $this->connection = $resource->getConnection(); $this->storeManager = $storeManager; $this->config = $config; $this->queryGenerator = $queryGenerator ?: ObjectManager::getInstance()->get(QueryGenerator::class); $this->metadataPool = $metadataPool ?: ObjectManager::getInstance()->get(MetadataPool::class); $this->tableMaintainer = $tableMaintainer ?: ObjectManager::getInstance()->get(TableMaintainer::class); }
测试
在集成测试中,对象管理器可用于为夹具生成新的对象。作为对这一点的简单而直接的解释,我们可以说对象管理器的直接调用取代了新的PHP方法。例如,Magento\AdobeStockImage\Test\Integration\Model\SaveImageTest
/** * Test with image. * * @param array $documentData * @param string $sourceFile * @param string $destinationPath * @return void * @dataProvider getSaveTestDataProvider */ public function testSave(array $documentData, string $sourceFile, string $destinationPath): void { $this->deleteImage($destinationPath); $document = $this->getDocument($documentData); $saveImage = Bootstrap::getObjectManager()->create(SaveImageInterface::class); $saveImage->execute( $document, $this->getImageFilePath($sourceFile), $destinationPath ); $this->assertImageSavedToDirectory($destinationPath); $this->assertAssets($destinationPath, $documentData); $this->deleteImage($destinationPath); }
魔术方法
像上面描述的测试步骤中的对象管理器可以直接在 PHP 魔术方法中调用,以启动一个新实例或已经存在。作为一个例子,让我们在Magento\Framework\DB\Select中检查__wakeup()魔术方法。
/** * Init not serializable fields * * @return void * @since 100.0.11 */ public function __wakeup() { $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->_adapter = $objectManager->get(ResourceConnection::class)->getConnection(); $this->selectRenderer = $objectManager->get(\Magento\Framework\DB\Select\SelectRenderer::class); }
总而言之,我们可以说对象管理器方法是Magento 2平台中调度的对象生命周期。它用于对象初始化,共享对象管理。它有特定的使用规则,遵循这些规则可以保证项目的稳定性和可维护性。