Magento 2创建shell脚本

4.16K 浏览开发笔记

Magento 2创建shell脚本

shell脚本是在Magento中快速运行维护命令的好方法。在Magento 2中,shell脚本通过命令行执行

php bin/magento  

背景

Magento CLI在MagentoFrameworkConsoleCli类中定义,这是一个Symphony Application。应用程序从Symphony application中定义的运行命令开始运行,该命令执行初始配置,例如将输入设置为控制台输入,将输出设置为控制台。一旦初始化完成,应用程序doRun()方法就会被调用。此方法执行以下步骤:

  • 检查是否传递了版本参数以显示版本信息。

  • 如果没有请求版本信息,脚本将检索命令名。

  • 检查是否传递了帮助参数,如果是,则将命令名设置为“帮助”。

  • 如果没有请求帮助信息,也没有传递命令,则命令名将设置为应用程序默认命令,在Magento 2中,该命令将列出可用的命令。

  • 接下来,它在已注册命令列表中查找该命令。

  • 最后,它执行命令并返回退出代码。

开始编码

在编写与类别交互的扩展时,最好运行Magento测试框架提供的Catalog测试,以确保没有中断Magento功能。运行这些测试的缺点是会产生大量的测试类别和产品,从而影响系统的性能,有时无法继续开发和测试。在本文中,我们将构建一个命令行工具来清理测试框架生成的测试类别。因此,不需要恢复数据库,在开发期间重新运行测试就更容易了。为了本文的目的,调用脚本的命令将是catalog:category:clean,即在执行以下控制台命令时将调用我们的命令


php bin/magento catalog:category:clean

1.创建命令类

该命令通过扩展SymphonyCommand类的类来处理。创建类后,需要配置类并将其绑定到命令。catalog:category:clean。这是通过将类名属性设置为我们的命令并调用SymphonyCommand配置()方法来完成的。


class CatalogCleanCommand extends Command
{
   protected function configure()
   {
       $this->setName('catalog:category:clean')
           ->setDescription('Cleans the catalog from extra categories (ending with more than 4 numbers');
       parent::configure();
   }
}

在本文中,我们将类放置在名称空间ClanceCommandConsoleCommand下。

2.使用CLI工具注册类

当我们调用命令来清理类别时,称为CLI应用程序的doRun将获取需要执行该命令的类。这是通过在di.xml文件中注册我们的类来处理的,如下所示:


// di.xml

   
       
           ClounceCommandsConsoleCommandCatalogCleanCommand

       
   

注意,项目名是一个任意名称,但是,将命令项命名为与没有冒号分隔符的命令名相同并在末尾附加工作‘Command’是Magento的最佳实践。

2.1检查该班是否已适当注册

现在我们已经创建了命令类,并且已经在di.xml中注册了它,我们可以检查命令是否已注册。若要从命令行执行此操作,请运行命令


php bin/magento

这将加载可用命令的列表,如果所有命令都已正确设置,则我们的命令应该显示在列表中。

图1:CLI命令清单

图1显示了列表中的新命令,其中包含指定的描述。注意,第一个冒号之前的单词用于分组。这是由SymphonyApplication类自动完成的。

3.处理命令

立即运行命令,返回图2中的错误。

图2:缺少EXECUTE()函数

3.1初始化对象管理器

在使用命令执行任何有用的操作之前,我们需要初始化对象管理器。这是Magento中用于初始化类的基类。为了本文的目的,将使用Admin范围初始化对象管理器。


/**
* Constructor
*
* @param ObjectManagerFactory $objectManagerFactory
*/
public function __construct(
   ObjectManagerFactory $objectManagerFactory
){
   $params = $_SERVER;
   $params[StoreManager::PARAM_RUN_CODE] = 'admin';
   $params[StoreManager::PARAM_RUN_TYPE] = 'store';
   $this->objectManager = $objectManagerFactory->create($params);
   parent::__construct();
}

3.2定义命令执行

既然有了对象管理器,就可以实现该命令了。首先重写execute()方法,并将一些信息输出到控制台,以便用户知道该命令已经找到并开始执行。


/**
* @param InputInterface $input
* @param OutputInterface $output
* @throws MagentoFrameworkExceptionLocalizedException
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
   $output->writeln('Starting Category Cleanup');
}

值得注意的是,writeln()命令可以解释一些标记来对输出进行样式化。根据SiteSymfony 2控制台组件,通过示例Symfony 2控制台组件(示例)-输出writeln()命令提供了4个标记:

  • 信息-将所附文本更改为绿色。

  • 注释-将所附文本更改为黄色

  • 问题-在青色背景上以黑色显示所附文字。

  • 错误-文本显示在红色背景上,白色文本颜色。

图3:控制台输出标记

3.2.1获取类别集合

本文中的示例将清理由测试框架创建的类别。要获得类别,需要创建类别集合。使用对象管理器,我们获得类别集合,如下所示。


/** @var MagentoCatalogModelResourceModelCategoryCollectionFactory $categoryCollectionFactory */
$categoryCollectiOnFactory= $this->objectManager->get('MagentoCatalogModelResourceModelCategoryCollectionFactory');

/** @var MagentoCatalogModelResourceModelCategoryCollection $categoryCollection */
$categoryCollection = $categoryCollectionFactory->create();
$categoryCollection->addAttributeToSelect('name');

注意,我们已经将‘name’属性添加到集合中。在Magento 2中,Eav集合不会自动向集合添加自定义属性。

3.2.2删除测试类别

获得类别集合后,可以识别和删除测试类别。通过对所创建的测试数据的快速分析,测试框架创建的类别最终都有一个通常为8位或更长的数字序列。为了简单起见,我们的命令将删除末尾至少有4个字符的任何类别。


/** @var MagentoCatalogModelCategory $category */
foreach ($categoryCollection as $category) {
   if (preg_match('/\d{4,}$/', $category->getName()) == 1) {
       $output->writeln('Deleting Cateogry with Name: "'. $category->getName() . '"');
       $category->delete();
   }
}

注意,虽然我们的集合只定义了属性名,但它仍然返回一个类别对象。但是,类别对象将只具有catalog_category_entity表和name属性。这足以允许在定义类别ID时删除类别。

当我们试图运行代码时,会出现一个错误,即不允许使用Delete操作。发生此错误的原因是类别模型要求只从安全区域执行删除操作。

图4:禁止操作

3.2.3设置安全区

看着RemoveAction功能,注意到执行了检查以确保从安全区域调用操作。因为我们打算从命令行中删除这些类别,所以我们需要将脚本设置为在安全区域中运行。这是通过设置isSecureArea在登记处。


/**
* @var MagentoFrameworkRegistry
*/
$registry = $this->objectManager->get('MagentoFrameworkRegistry');
$registry->register('isSecureArea', true);

既然脚本已被标记为安全,则可以执行命令并删除类别。

图5:代码执行

全部代码

php
/**
* Copyright © 2015 Clounce. All rights reserved.
* See COPYING.txt for license details.
*/
namespace ClounceCommandsConsoleCommand;

use MagentoFrameworkAppObjectManagerConfigLoader;
use MagentoFrameworkAppObjectManagerFactory;
use MagentoFrameworkAppState;
use MagentoStoreModelStoreManager;
use SymfonyComponentConsoleCommandCommand;
use SymfonyComponentConsoleInputInputInterface;
use SymfonyComponentConsoleOutputOutputInterface;

class CatalogCleanCommand extends Command
{
   /**
    * @var MagentoFrameworkObjectManagerInterface
    */
   protected $objectManager;

   /**
    * Constructor
    *
    * @param ObjectManagerFactory $objectManagerFactory
    */
   public function __construct(
       ObjectManagerFactory $objectManagerFactory
   ){
       $params = $_SERVER;
       $params[StoreManager::PARAM_RUN_CODE] = 'admin';
       $params[StoreManager::PARAM_RUN_TYPE] = 'store';
       $this->objectManager = $objectManagerFactory->create($params);
       parent::__construct();
   }

   protected function configure()
   {
       $this->setName('catalog:category:clean')
           ->setDescription('Cleans the catalog from extra categories (ending with more than 4 numbers');
       parent::configure();
   }

   /**
    * @param InputInterface $input
    * @param OutputInterface $output
    * @throws MagentoFrameworkExceptionLocalizedException
    * @return null|int null or 0 if everything went fine, or an error code
    */
   protected function execute(InputInterface $input, OutputInterface $output)
   {
       $output->writeln('Starting Category Cleanup');

       /**
        * @var MagentoFrameworkRegistry
        */
       $registry = $this->objectManager->get('MagentoFrameworkRegistry');
       $registry->register('isSecureArea', true);

       /** @var MagentoCatalogModelResourceModelCategoryCollectionFactory $categoryCollectionFactory */
       $categoryCollectionFactory = $this->objectManager->get('MagentoCatalogModelResourceModelCategoryCollectionFactory');

       /** @var MagentoCatalogModelResourceModelCategoryCollection $categoryCollection */
       $categoryCollection = $categoryCollectionFactory->create();
       $categoryCollection->addAttributeToSelect('name');

       /** @var MagentoCatalogModelCategory $category */
       foreach ($categoryCollection as $category) {
           if (preg_match('/\d{4,}$/', $category->getName()) == 1) {
               $output->writeln('Deleting Category with Name: "'. $category->getName() . '"');
               $category->delete();
           }
       }

       $output->writeln('Categories Cleaned');

       return 0;
   }
}

参考文献

最后于 11月前 被max编辑 ,原因:
0