Magento 2:向订单详情页添加自定义功能按钮

Magento 2:向订单详情页添加自定义功能按钮

本文档详细介绍了如何在 Magento 2 后台的订单详情页面添加一个自定义按钮,并实现点击后触发特定功能。通过本文,你将学习如何创建模块、配置路由、编写控制器和插件,最终实现自定义按钮的功能。同时,本文也考虑了启用 “Add Secret Key to URLs” 的情况,提供更全面的解决方案。

创建模块

首先,我们需要创建一个自定义模块。按照 Magento 2 的模块结构,创建以下文件:

  1. 注册文件 (registration.php)

    <?php MagentoFrameworkComponentComponentRegistrar::register(     MagentoFrameworkComponentComponentRegistrar::MODULE,     'MG_Dropship',     __DIR__ );

    这个文件告诉 Magento 2 注册名为 MG_Dropship 的模块。

  2. 模块配置文件 (etc/module.xml)

    <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">     <module name="MG_Dropship" setup_version="1.0.0"/> </config>

    这个文件声明了模块的名称和版本。

配置依赖注入 (DI)

接下来,我们需要通过 di.xml 文件配置依赖注入,以便在订单详情页添加自定义按钮。

<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">    <type name="MagentoSalesBlockAdminhtmlOrderView">        <plugin name="addCustomButton" type="MGDropshipPluginSalesBlockAdminhtmlOrderButton"/>    </type> </config>

这个配置使用了一个插件(MGDropshipPluginSalesBlockAdminhtmlOrderButton)来拦截 MagentoSalesBlockAdminhtmlOrderView 类的 beforeSetLayout 方法,从而可以在订单详情页添加自定义按钮。

配置路由

我们需要定义一个路由,以便处理自定义按钮的点击事件

<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">     <router id="admin">         <route id="mg_dropship" frontName="mg_dropship">             <module name="MG_Dropship" />         </route>     </router> </config>

这个文件定义了一个名为 mg_dropship 的 admin 路由,frontName 也设置为 mg_dropship。

创建控制器

我们需要创建一个控制器来处理自定义按钮的点击事件

<?php namespace MGDropshipControllerAdminhtmlOrder;  class Index extends MagentoSalesControllerAdminhtmlOrder {     /**      * @var PsrLogLoggerInterface      */     protected $logger;      /**      * Index constructor.      *      * @param MagentoBackendAppActionContext $context      * @param MagentoFrameworkRegistry $coreRegistry      * @param MagentoFrameworkAppResponseHttpFileFactory $fileFactory      * @param MagentoSalesModelOrderEmailSenderOrderSender $orderSender      * @param MagentoBackendModelViewResultForwardFactory $resultForwardFactory      * @param MagentoFrameworkViewResultPageFactory $resultPageFactory      * @param PsrLogLoggerInterface $logger      */     public function __construct(         MagentoBackendAppActionContext $context,         MagentoFrameworkRegistry $coreRegistry,         MagentoFrameworkAppResponseHttpFileFactory $fileFactory,         MagentoSalesModelOrderEmailSenderOrderSender $orderSender,         MagentoBackendModelViewResultForwardFactory $resultForwardFactory,         MagentoFrameworkViewResultPageFactory $resultPageFactory,         PsrLogLoggerInterface $logger     ) {         $this->logger = $logger;         parent::__construct($context, $coreRegistry, $fileFactory, $orderSender, $resultForwardFactory, $resultPageFactory);     }      /**      * Execute action      *      * @throws MagentoFrameworkExceptionLocalizedException|Exception      */     public function execute()     {         // In case you want to do something with the order         $order = $this->_initOrder();         if ($order) {             try {                 // TODO: Do something with the order                 $this->messageManager->addSuccessMessage(__('We did something!'));             } catch (MagentoFrameworkExceptionLocalizedException $e) {                 $this->messageManager->addErrorMessage($e->getMessage());             } catch (Exception $e) {                 $this->messageManager->addErrorMessage(__('We can't process your request' . $e->getMessage()));                 $this->logger->critical($e);             }              return $this->resultredirectFactory->create()->setPath(                 'sales/order/view',                 [                    'order_id' => $order->getEntityId()                 ]              );             }          return $this->resultRedirectFactory->create()->setPath('sales/*/');     }      /**      * @return bool      */     protected function _isAllowed()     {         return $this->_authorization->isAllowed('MG_Dropship::order_dosomething');     } }

这个控制器继承自 MagentoSalesControllerAdminhtmlOrder,并重写了 execute 方法。在 execute 方法中,你可以编写自定义逻辑来处理订单。 关键是使用 $this->_initOrder() 来初始化订单对象。同时,需要实现 _isAllowed 方法来控制访问权限。

创建插件

我们需要创建一个插件来向订单详情页添加自定义按钮。

<?php namespace MGDropshipPluginSalesBlockAdminhtmlOrder;  use MagentoSalesBlockAdminhtmlOrderView as OrderView;  class Button {     public function beforeSetLayout(OrderView $subject)     {         if ($subject->getOrder()) {             $message = __('Are you sure you want to Do Something?');             $subject->addButton(                 'do_something',                 [                'label' => __('Do Something'),                'class' => 'do_something',                'onclick' => "confirmSetLocation('{$message}', '{$subject->getUrl('mg_dropship/order/index')}')"                ]             );         }     } }

这个插件拦截了 MagentoSalesBlockAdminhtmlOrderView 类的 beforeSetLayout 方法,并使用 $subject->addButton 方法添加了一个名为 do_something 的按钮。onclick 属性定义了点击按钮后执行的 JavaScript 代码,它会弹出一个确认框,并在确认后跳转到 mg_dropship/order/index 路由。

定义权限

为了控制用户访问自定义功能的权限,需要在 etc/adminhtml/acl.xml 文件中定义权限规则。

<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Acl/etc/acl.xsd">     <acl>         <resources>             <resource id="Magento_Backend::admin">                 <resource id="Magento_Sales::sales">                     <resource id="Magento_Sales::orders">                         <resource id="MG_Dropship::order_dosomething" title="Do Something" sortOrder="10" />                     </resource>                 </resource>             </resource>         </resources>     </acl> </config>

这个文件定义了一个名为 MG_Dropship::order_dosomething 的权限规则,你需要在后台配置用户角色,授予他们这个权限才能访问自定义功能。

启用 “Add Secret Key to URLs” 的情况

当启用 “Add Secret Key to URLs” 时,Magento 会自动在 URL 中添加一个 secret key,以增加安全性。 以上代码已经兼容这种情况,$subject->getUrl(‘mg_dropship/order/index’) 会自动生成包含 secret key 的 URL。

总结

通过以上步骤,你就可以在 Magento 2 后台的订单详情页添加一个自定义按钮,并实现点击后触发特定功能。请确保在修改代码后清除缓存,并检查是否正确配置了权限。

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享