Magento 2创建shell脚本
Magento 2创建shell脚本
shell脚本是在Magento中快速运行维护命令的好方法。在Magento 2中,shell脚本通过命令行执行
php bin/magento <command name> <command parameters>
背景
Magento CLI在MagentoFrameworkConsoleCli类中定义,这是一个Symphony Application。应用程序从Symphony application中定义的运行命令开始运行,该命令执行初始配置,例如将输入设置为控制台输入,将输出设置为控制台。一旦初始化完成,应用程序doRun()方法就会被调用。此方法执行以下步骤:
-
检查是否传递了版本参数以显示版本信息。
-
如果没有请求版本信息,脚本将检索命令名。
-
检查是否传递了帮助参数,如果是,则将命令名设置为“帮助”。
-
如果没有请求帮助信息,也没有传递命令,则命令名将设置为应用程序默认命令,在Magento 2中,该命令将列出可用的命令。
-
接下来,它在已注册命令列表中查找该命令。
-
最后,它执行命令并返回退出代码。
开始编码
在编写与类别交互的扩展时,最好运行Magento测试框架提供的Catalog测试,以确保没有中断Magento功能。运行这些测试的缺点是会产生大量的测试类别和产品,从而影响系统的性能,有时无法继续开发和测试。在本文中,我们将构建一个命令行工具来清理测试框架生成的测试类别。因此,不需要恢复数据库,在开发期间重新运行测试就更容易了。为了本文的目的,调用脚本的命令将是catalog:category:clean
,即在执行以下控制台命令时将调用我们的命令
<br><span style="padding-right: 0.1px">php bin/magento catalog:category:clean</span>
1.创建命令类
该命令通过扩展SymphonyCommand类的类来处理。创建类后,需要配置类并将其绑定到命令。catalog:category:clean
。这是通过将类名属性设置为我们的命令并调用SymphonyCommand配置()方法来完成的。
<br><span style="padding-right: 0.1px">class CatalogCleanCommand extends Command</span><br><span style="padding-right: 0.1px">{</span><br><span style="padding-right: 0.1px"> protected function configure()</span><br><span style="padding-right: 0.1px"> {</span><br><span style="padding-right: 0.1px"> $this->setName(&#39;catalog:category:clean&#39;)</span><br><span style="padding-right: 0.1px"> ->setDescription(&#39;Cleans the catalog from extra categories (ending with more than 4 numbers&#39;);</span><br><span style="padding-right: 0.1px"> parent::configure();</span><br><span style="padding-right: 0.1px"> }</span><br><span style="padding-right: 0.1px">}</span>
在本文中,我们将类放置在名称空间ClanceCommandConsoleCommand下。
2.使用CLI工具注册类
当我们调用命令来清理类别时,称为CLI应用程序的doRun将获取需要执行该命令的类。这是通过在di.xml文件中注册我们的类来处理的,如下所示:
<br><span style="padding-right: 0.1px">// di.xml</span><br><span style="padding-right: 0.1px"><type name="MagentoFrameworkConsoleCommandList"></span><br><span style="padding-right: 0.1px"> <arguments></span><br><span style="padding-right: 0.1px"> <argument name="commands" xsi:type="array"></span><br><span style="padding-right: 0.1px"> <item name="catalogCategoryCleanCommand" xsi:type="object">ClounceCommandsConsoleCommandCatalogCleanCommand</item></span><br><br><span style="padding-right: 0.1px"> </argument></span><br><span style="padding-right: 0.1px"> </arguments></span><br><span style="padding-right: 0.1px"></type></span>
注意,项目名是一个任意名称,但是,将命令项命名为与没有冒号分隔符的命令名相同并在末尾附加工作‘Command’是Magento的最佳实践。
2.1检查该班是否已适当注册
现在我们已经创建了命令类,并且已经在di.xml中注册了它,我们可以检查命令是否已注册。若要从命令行执行此操作,请运行命令
<br><span style="padding-right: 0.1px">php bin/magento</span>
这将加载可用命令的列表,如果所有命令都已正确设置,则我们的命令应该显示在列表中。
图1:CLI命令清单
图1显示了列表中的新命令,其中包含指定的描述。注意,第一个冒号之前的单词用于分组。这是由SymphonyApplication类自动完成的。
3.处理命令
立即运行命令,返回图2中的错误。
图2:缺少EXECUTE()函数
3.1初始化对象管理器
在使用命令执行任何有用的操作之前,我们需要初始化对象管理器。这是Magento中用于初始化类的基类。为了本文的目的,将使用Admin范围初始化对象管理器。
<br><span style="padding-right: 0.1px">/**</span><br><span style="padding-right: 0.1px"> * Constructor</span><br><span style="padding-right: 0.1px"> *</span><br><span style="padding-right: 0.1px"> * @param ObjectManagerFactory $objectManagerFactory</span><br><span style="padding-right: 0.1px"> */</span><br><span style="padding-right: 0.1px">public function __construct(</span><br><span style="padding-right: 0.1px"> ObjectManagerFactory $objectManagerFactory</span><br><span style="padding-right: 0.1px">){</span><br><span style="padding-right: 0.1px"> $params = $_SERVER;</span><br><span style="padding-right: 0.1px"> $params[StoreManager::PARAM_RUN_CODE] = &#39;admin&#39;;</span><br><span style="padding-right: 0.1px"> $params[StoreManager::PARAM_RUN_TYPE] = &#39;store&#39;;</span><br><span style="padding-right: 0.1px"> $this->objectManager = $objectManagerFactory->create($params);</span><br><span style="padding-right: 0.1px"> parent::__construct();</span><br><span style="padding-right: 0.1px">}</span>
3.2定义命令执行
既然有了对象管理器,就可以实现该命令了。首先重写execute()
方法,并将一些信息输出到控制台,以便用户知道该命令已经找到并开始执行。
<br><span style="padding-right: 0.1px">/**</span><br><span style="padding-right: 0.1px"> * @param InputInterface $input</span><br><span style="padding-right: 0.1px"> * @param OutputInterface $output</span><br><span style="padding-right: 0.1px"> * @throws MagentoFrameworkExceptionLocalizedException</span><br><span style="padding-right: 0.1px"> */</span><br><span style="padding-right: 0.1px">protected function execute(InputInterface $input, OutputInterface $output)</span><br><span style="padding-right: 0.1px">{</span><br><span style="padding-right: 0.1px"> $output->writeln(&#39;<info>Starting Category Cleanup</info>&#39;);</span><br><span style="padding-right: 0.1px">}</span>
值得注意的是,writeln()命令可以解释一些标记来对输出进行样式化。根据SiteSymfony 2控制台组件,通过示例Symfony 2控制台组件(示例)-输出writeln()命令提供了4个标记:
-
信息-将所附文本更改为绿色。
-
注释-将所附文本更改为黄色
-
问题-在青色背景上以黑色显示所附文字。
-
错误-文本显示在红色背景上,白色文本颜色。
图3:控制台输出标记
3.2.1获取类别集合
本文中的示例将清理由测试框架创建的类别。要获得类别,需要创建类别集合。使用对象管理器,我们获得类别集合,如下所示。
<br><span style="padding-right: 0.1px">/** @var MagentoCatalogModelResourceModelCategoryCollectionFactory $categoryCollectionFactory */</span><br><span style="padding-right: 0.1px">$categoryCollectiOnFactory= $this->objectManager->get(&#39;MagentoCatalogModelResourceModelCategoryCollectionFactory&#39;);</span><br><br><span style="padding-right: 0.1px">/** @var MagentoCatalogModelResourceModelCategoryCollection $categoryCollection */</span><br><span style="padding-right: 0.1px">$categoryCollection = $categoryCollectionFactory->create();</span><br><span style="padding-right: 0.1px">$categoryCollection->addAttributeToSelect(&#39;name&#39;);</span>
注意,我们已经将‘name’属性添加到集合中。在Magento 2中,Eav集合不会自动向集合添加自定义属性。
3.2.2删除测试类别
获得类别集合后,可以识别和删除测试类别。通过对所创建的测试数据的快速分析,测试框架创建的类别最终都有一个通常为8位或更长的数字序列。为了简单起见,我们的命令将删除末尾至少有4个字符的任何类别。
<br><span style="padding-right: 0.1px">/** @var MagentoCatalogModelCategory $category */</span><br><span style="padding-right: 0.1px">foreach ($categoryCollection as $category) {</span><br><span style="padding-right: 0.1px"> if (preg_match(&#39;/\d{4,}$/&#39;, $category->getName()) == 1) {</span><br><span style="padding-right: 0.1px"> $output->writeln(&#39;<comment>Deleting Cateogry with Name: "&#39;. $category->getName() . &#39;"</comment>&#39;);</span><br><span style="padding-right: 0.1px"> $category->delete();</span><br><span style="padding-right: 0.1px"> }</span><br><span style="padding-right: 0.1px">}</span>
注意,虽然我们的集合只定义了属性名,但它仍然返回一个类别对象。但是,类别对象将只具有catalog_category_entity
表和name属性。这足以允许在定义类别ID时删除类别。
当我们试图运行代码时,会出现一个错误,即不允许使用Delete操作。发生此错误的原因是类别模型要求只从安全区域执行删除操作。
图4:禁止操作
3.2.3设置安全区
看着RemoveAction
功能,注意到执行了检查以确保从安全区域调用操作。因为我们打算从命令行中删除这些类别,所以我们需要将脚本设置为在安全区域中运行。这是通过设置isSecureArea
在登记处。
<br><span style="padding-right: 0.1px">/**</span><br><span style="padding-right: 0.1px"> * @var MagentoFrameworkRegistry</span><br><span style="padding-right: 0.1px"> */</span><br><span style="padding-right: 0.1px">$registry = $this->objectManager->get(&#39;MagentoFrameworkRegistry&#39;);</span><br><span style="padding-right: 0.1px">$registry->register(&#39;isSecureArea&#39;, true);</span>
既然脚本已被标记为安全,则可以执行命令并删除类别。
图5:代码执行
全部代码
<span style="padding-right: 0.1px"><span><?</span><span>php</span></span><br><span style="padding-right: 0.1px"><span>/**</span></span><br><span style="padding-right: 0.1px"> <span>* Copyright © 2015 Clounce. All rights reserved.</span></span><br><span style="padding-right: 0.1px"> <span>* See COPYING.txt for license details.</span></span><br><span style="padding-right: 0.1px"> <span>*/</span></span><br><span style="padding-right: 0.1px"><span>namespace</span> <span>ClounceCommandsConsoleCommand</span>;</span><br><br><span style="padding-right: 0.1px"><span>use</span> <span>MagentoFrameworkAppObjectManagerConfigLoader</span>;</span><br><span style="padding-right: 0.1px"><span>use</span> <span>MagentoFrameworkAppObjectManagerFactory</span>;</span><br><span style="padding-right: 0.1px"><span>use</span> <span>MagentoFrameworkAppState</span>;</span><br><span style="padding-right: 0.1px"><span>use</span> <span>MagentoStoreModelStoreManager</span>;</span><br><span style="padding-right: 0.1px"><span>use</span> <span>SymfonyComponentConsoleCommandCommand</span>;</span><br><span style="padding-right: 0.1px"><span>use</span> <span>SymfonyComponentConsoleInputInputInterface</span>;</span><br><span style="padding-right: 0.1px"><span>use</span> <span>SymfonyComponentConsoleOutputOutputInterface</span>;</span><br><br><span style="padding-right: 0.1px"><span>class</span> <span>CatalogCleanCommand</span> <span>extends</span> <span>Command</span></span><br><span style="padding-right: 0.1px">{</span><br><span style="padding-right: 0.1px"> <span>/**</span></span><br><span style="padding-right: 0.1px"> <span>* @var MagentoFrameworkObjectManagerInterface</span></span><br><span style="padding-right: 0.1px"> <span>*/</span></span><br><span style="padding-right: 0.1px"> <span>protected</span> <span>$objectManager</span>;</span><br><br><span style="padding-right: 0.1px"> <span>/**</span></span><br><span style="padding-right: 0.1px"> <span>* Constructor</span></span><br><span style="padding-right: 0.1px"> <span>*</span></span><br><span style="padding-right: 0.1px"> <span>* @param ObjectManagerFactory $objectManagerFactory</span></span><br><span style="padding-right: 0.1px"> <span>*/</span></span><br><span style="padding-right: 0.1px"> <span>public</span> <span>function</span> <span>__construct</span>(</span><br><span style="padding-right: 0.1px"> <span>ObjectManagerFactory</span> <span>$objectManagerFactory</span></span><br><span style="padding-right: 0.1px"> ){</span><br><span style="padding-right: 0.1px"> <span>$params</span> <span>=</span> <span>$_SERVER</span>;</span><br><span style="padding-right: 0.1px"> <span>$params</span>[<span>StoreManager</span>::<span>PARAM_RUN_CODE</span>] <span>=</span> <span>&#39;admin&#39;</span>;</span><br><span style="padding-right: 0.1px"> <span>$params</span>[<span>StoreManager</span>::<span>PARAM_RUN_TYPE</span>] <span>=</span> <span>&#39;store&#39;</span>;</span><br><span style="padding-right: 0.1px"> <span>$this</span><span>-></span><span>objectManager</span> <span>=</span> <span>$objectManagerFactory</span><span>-></span><span>create</span>(<span>$params</span>);</span><br><span style="padding-right: 0.1px"> <span>parent</span>::<span>__construct</span>();</span><br><span style="padding-right: 0.1px"> }</span><br><br><span style="padding-right: 0.1px"> <span>protected</span> <span>function</span> <span>configure</span>()</span><br><span style="padding-right: 0.1px"> {</span><br><span style="padding-right: 0.1px"> <span>$this</span><span>-></span><span>setName</span>(<span>&#39;catalog:category:clean&#39;</span>)</span><br><span style="padding-right: 0.1px"> <span>-></span><span>setDescription</span>(<span>&#39;Cleans the catalog from extra categories (ending with more than 4 numbers&#39;</span>);</span><br><span style="padding-right: 0.1px"> <span>parent</span>::<span>configure</span>();</span><br><span style="padding-right: 0.1px"> }</span><br><br><span style="padding-right: 0.1px"> <span>/**</span></span><br><span style="padding-right: 0.1px"> <span>* @param InputInterface $input</span></span><br><span style="padding-right: 0.1px"> <span>* @param OutputInterface $output</span></span><br><span style="padding-right: 0.1px"> <span>* @throws MagentoFrameworkExceptionLocalizedException</span></span><br><span style="padding-right: 0.1px"> <span>* @return null|int null or 0 if everything went fine, or an error code</span></span><br><span style="padding-right: 0.1px"> <span>*/</span></span><br><span style="padding-right: 0.1px"> <span>protected</span> <span>function</span> <span>execute</span>(<span>InputInterface</span> <span>$input</span>, <span>OutputInterface</span> <span>$output</span>)</span><br><span style="padding-right: 0.1px"> {</span><br><span style="padding-right: 0.1px"> <span>$output</span><span>-></span><span>writeln</span>(<span>&#39;<info>Starting Category Cleanup</info>&#39;</span>);</span><br><br><span style="padding-right: 0.1px"> <span>/**</span></span><br><span style="padding-right: 0.1px"> <span>* @var MagentoFrameworkRegistry</span></span><br><span style="padding-right: 0.1px"> <span>*/</span></span><br><span style="padding-right: 0.1px"> <span>$registry</span> <span>=</span> <span>$this</span><span>-></span><span>objectManager</span><span>-></span><span>get</span>(<span>&#39;MagentoFrameworkRegistry&#39;</span>);</span><br><span style="padding-right: 0.1px"> <span>$registry</span><span>-></span><span>register</span>(<span>&#39;isSecureArea&#39;</span>, <span>true</span>);</span><br><br><span style="padding-right: 0.1px"> <span>/** @var MagentoCatalogModelResourceModelCategoryCollectionFactory $categoryCollectionFactory */</span></span><br><span style="padding-right: 0.1px"> <span>$categoryCollectionFactory</span> <span>=</span> <span>$this</span><span>-></span><span>objectManager</span><span>-></span><span>get</span>(<span>&#39;MagentoCatalogModelResourceModelCategoryCollectionFactory&#39;</span>);</span><br><br><span style="padding-right: 0.1px"> <span>/** @var MagentoCatalogModelResourceModelCategoryCollection $categoryCollection */</span></span><br><span style="padding-right: 0.1px"> <span>$categoryCollection</span> <span>=</span> <span>$categoryCollectionFactory</span><span>-></span><span>create</span>();</span><br><span style="padding-right: 0.1px"> <span>$categoryCollection</span><span>-></span><span>addAttributeToSelect</span>(<span>&#39;name&#39;</span>);</span><br><br><span style="padding-right: 0.1px"> <span>/** @var MagentoCatalogModelCategory $category */</span></span><br><span style="padding-right: 0.1px"> <span>foreach</span> (<span>$categoryCollection</span> <span>as</span> <span>$category</span>) {</span><br><span style="padding-right: 0.1px"> <span>if</span> (<span>preg_match</span>(<span>&#39;/\d{4,}$/&#39;</span>, <span>$category</span><span>-></span><span>getName</span>()) <span>==</span> <span>1</span>) {</span><br><span style="padding-right: 0.1px"> <span>$output</span><span>-></span><span>writeln</span>(<span>&#39;<comment>Deleting Category with Name: "&#39;</span>. <span>$category</span><span>-></span><span>getName</span>() . <span>&#39;"</comment>&#39;</span>);</span><br><span style="padding-right: 0.1px"> <span>$category</span><span>-></span><span>delete</span>();</span><br><span style="padding-right: 0.1px"> }</span><br><span style="padding-right: 0.1px"> }</span><br><br><span style="padding-right: 0.1px"> <span>$output</span><span>-></span><span>writeln</span>(<span>&#39;<info>Categories Cleaned</info>&#39;</span>);</span><br><br><span style="padding-right: 0.1px"> <span>return</span> <span>0</span>;</span><br><span style="padding-right: 0.1px"> }</span><br><span style="padding-right: 0.1px">}</span>