如何在Magento 2中使用插件,首选项重写块,模型,控制器,助手

当您在Magento 2中使用块,模型,控制器,帮助器时,如果修改核心文件不好,这可能会对另一个程序产生一定的影响。因此,今天,我强烈建议以一种便捷的方式重写所有文件的好方法。本主题向您展示在Magento 2中使用插件和首选项时如何重写块,模型,控制器,帮助器

重写块,模型,控制器,助手的概述

方法1:使用插件

由于不便之处,如果使用首选项,则Plugin似乎是重写Magento 2中的块,模型控制器,帮助器的明智选择。使用Plugin,您可以在代码/目标类的功能之前,之后和周围执行代码。无需替换,这只是在核心代码之前/之后插入一些代码,然后观察核心/目标类的功能,并在核心/目标类的功能之间运行我们的代码。另外,有可能来自多个模块的插件在相同核心/目标类的功能之前/之后/周围插入自己的代码。

块覆盖

app/code/Mageplaza/HelloWorld/etc/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="Magento\Catalog\Block\Product\View">
        <plugin name="Mageplaza-yourmodule-product-block" type="Mageplaza\HelloWorld\Plugin\ProductPlugin" sortOrder="5" />
    </type>
</config>

在这里启用包含方法之前,之后和周围的所有方法。

  • 首先,beforeGetProduct方法将被激活。
  • 接下来,aroundGetPrduct将处于活动状态。

注意:使用around方法意味着您可以在观察到的函数之前和之后直接插入代码。具体来说,我要提及的函数是getProduct()并且在class中观察到了Magento\Catalog\Block\Product\View

  • 最后,afterGetProduct方法将被激活。您可以查看var/log/debug.log并确认方法的执行顺序。

app/code/Mageplaza/HelloWorld/Plugin/ProductPlugin.php

<?php
 
namespace Mageplaza\HelloWorld\Plugin;
 
class ProductPlugin
{    
    public function beforeGetProduct(\Magento\Catalog\Block\Product\View $subject)
    {
        // logging to test override    
        $logger = \Magento\Framework\App\ObjectManager::getInstance()->get('\Psr\Log\LoggerInterface');
        $logger->debug(__METHOD__ . ' - ' . __LINE__);        
    }
    
    public function afterGetProduct(\Magento\Catalog\Block\Product\View $subject, $result)
    {
        // logging to test override    
        $logger = \Magento\Framework\App\ObjectManager::getInstance()->get('\Psr\Log\LoggerInterface');
        $logger->debug(__METHOD__ . ' - ' . __LINE__);
        
        return $result;
    }
    
    public function aroundGetProduct(\Magento\Catalog\Block\Product\View $subject, \Closure $proceed)
    {
        // logging to test override    
        $logger = \Magento\Framework\App\ObjectManager::getInstance()->get('\Psr\Log\LoggerInterface');
        $logger->debug(__METHOD__ . ' - ' . __LINE__);
        
        // call the core observed function
        $returnValue = $proceed(); 
        
        // logging to test override        
        $logger->debug(__METHOD__ . ' - ' . __LINE__);
        
        return $returnValue;
    }    
}
?>

模型替代

app/code/Mageplaza/HelloWorld/etc/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="Magento\Catalog\Model\Product">
        <plugin name="Mageplaza-yourmodule-product-model" type="Mageplaza\HelloWorld\Plugin\ProductPlugin" sortOrder="1" />
    </type>    
</config>

在此命令中,启用“ before”和“ after”方法可以在观察到的方法之前和之后运行代码getName($product)

app/code/Mageplaza/HelloWorld/Plugin/ProductPlugin.php

<?php
 
namespace Mageplaza\HelloWorld\Plugin;
 
class ProductPlugin
{    
    public function beforeSetName(\Magento\Catalog\Model\Product $subject, $name)
    {
        // logging to test override    
        $logger = \Magento\Framework\App\ObjectManager::getInstance()->get('\Psr\Log\LoggerInterface');
        $logger->debug('Model Override Test before');
        
        return $name;
    }
            
    public function afterGetName(\Magento\Catalog\Model\Product $subject, $result)
    {            
        // logging to test override    
        $logger = \Magento\Framework\App\ObjectManager::getInstance()->get('\Psr\Log\LoggerInterface');
        $logger->debug('Model Override Test after');
        
        return $result;
    }    
}
?>

控制器

app/code/Mageplaza/HelloWorld/etc/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="Magento\Catalog\Controller\Product\View">
        <plugin name="MageplazaHelloWorldControllerProductView" type="Mageplaza\HelloWorld\Plugin\ProductPlugin" sortOrder="10"/>
    </type>
</config>

在此命令中,启用了“ around”方法以execute在class中存在的观察到的方法之前和之后运行代码Magento\Catalog\Controller\Product\View

app/code/Mageplaza/HelloWorld/Plugin/ProductPlugin.php

<?php
 
namespace Mageplaza\HelloWorld\Plugin;
 
class ProductPlugin
{        
    public function aroundExecute(\Magento\Catalog\Controller\Product\View $subject, \Closure $proceed)
    {
        // logging to test override    
        $logger = \Magento\Framework\App\ObjectManager::getInstance()->get('\Psr\Log\LoggerInterface');
        $logger->debug(__METHOD__ . ' - ' . __LINE__);
        
        // call the core observed function
        $returnValue = $proceed(); 
        
        // logging to test override        
        $logger->debug(__METHOD__ . ' - ' . __LINE__);
        
        return $returnValue;
    }
}
?>

协助

app/code/Mageplaza/HelloWorld/etc/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="Magento\Catalog\Helper\Data">
        <plugin name="MageplazaHelloWorldHelperData" type="Mageplaza\HelloWorld\Plugin\ProductPlugin" sortOrder="10"/>
    </type>
</config>

在此命令中,启用了“ around”方法以getProduct()在class中存在的观察到的方法之前和之后运行代码Magento\Catalog\Controller\Product\View

app/code/Mageplaza/HelloWorld/Plugin/ProductPlugin.php

<?php
 
namespace Mageplaza\HelloWorld\Plugin;
 
class ProductPlugin
{    
    public function aroundGetProduct(\Magento\Catalog\Helper\Data $subject, \Closure $proceed)
    {
        // logging to test override    
        $logger = \Magento\Framework\App\ObjectManager::getInstance()->get('\Psr\Log\LoggerInterface');
        $logger->debug(__METHOD__ . ' - ' . __LINE__);
        
        // call the core observed function
        $returnValue = $proceed(); 
        
        // logging to test override        
        $logger->debug(__METHOD__ . ' - ' . __LINE__);
        
        return $returnValue;
    }
}
?>

方法2:使用首选项

在Magento 1中,首选项被称为类重写。现在,您将知道您应该如何使用首选项来重写块,模型,控制器,助手。

块覆盖

app/code/Mageplaza/HelloWorld/etc/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">
    <preference for="Magento\Catalog\Block\Product\View" type="Mageplaza\HelloWorld\Block\Catalog\Product\View" />
</config>

那时,您可以重写getProduct()class的功能Magento\Catalog\Block\Product\View,那么您只需在var/log/debug.log此测试中登录一些消息即可。

app/code/Mageplaza/HelloWorld/Block/Catalog/Product/View.php

<?php
 
namespace Mageplaza\HelloWorld\Block\Catalog\Product;
 
class View extends \Magento\Catalog\Block\Product\View
{
    /**
     * Retrieve current product model
     *
     * @return \Magento\Catalog\Model\Product
     */
    public function getProduct()
    {
        // logging to test override    
        $logger = \Magento\Framework\App\ObjectManager::getInstance()->get('\Psr\Log\LoggerInterface');
        $logger->debug('Block Override Test');
        
        if (!$this->_coreRegistry->registry('product') && $this->getProductId()) {
            $product = $this->productRepository->getById($this->getProductId());
            $this->_coreRegistry->register('product', $product);
        }
        return $this->_coreRegistry->registry('product');
    }
}
?>

模型替代

app/code/Mageplaza/HelloWorld/etc/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">    
    <preference for="Magento\Catalog\Model\Product" type="Mageplaza\HelloWorld\Model\Catalog\Product" />
</config>

那时,您可以重写getName()class的功能Magento\Catalog\Model\Product,那么您只需在var/log/debug.log此测试中登录一些消息即可。

app/code/Mageplaza/HelloWorld/Model/Catalog/Product.php

<?php
 
namespace Mageplaza\HelloWorld\Model\Catalog;
 
class Product extends \Magento\Catalog\Model\Product
{    
    /**
     * Get product name
     *
     * @return string
     * @codeCoverageIgnoreStart
     */
    public function getName()
    {        
        // logging to test override    
        $logger = \Magento\Framework\App\ObjectManager::getInstance()->get('\Psr\Log\LoggerInterface');
        $logger->debug('Model Override Test');
    
        return $this->_getData(self::NAME);
    }
}
?>

控制器超越

app/code/Mageplaza/HelloWorld/etc/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">    
    <preference for="Magento\Catalog\Controller\Product\View" type="Mageplaza\HelloWorld\Controller\Catalog\Product\View" />
</config>

那时,您可以重写execute()class的功能Magento\Catalog\Controller\Product\View,那么您只需在var/log/debug.log此测试中登录一些消息即可。

app/code/Mageplaza/HelloWorld/Controller/Product/View.php

<?php
 
namespace Mageplaza\HelloWorld\Controller\Catalog\Product;
 
class View extends \Magento\Catalog\Controller\Product\View
{    
    /**
     * Product view action
     *
     * @return \Magento\Framework\Controller\Result\Forward|\Magento\Framework\Controller\Result\Redirect
     */
    public function execute()
    {
        // logging to test override    
        $logger = \Magento\Framework\App\ObjectManager::getInstance()->get('\Psr\Log\LoggerInterface');
        $logger->debug('Controller Override Test');
        
        // Get initial data from request
        $categoryId = (int) $this->getRequest()->getParam('category', false);
        $productId = (int) $this->getRequest()->getParam('id');
        $specifyOptions = $this->getRequest()->getParam('options');
 
        if ($this->getRequest()->isPost() && $this->getRequest()->getParam(self::PARAM_NAME_URL_ENCODED)) {
            $product = $this->_initProduct();
            if (!$product) {
                return $this->noProductRedirect();
            }
            if ($specifyOptions) {
                $notice = $product->getTypeInstance()->getSpecifyOptionMessage();
                $this->messageManager->addNotice($notice);
            }
            if ($this->getRequest()->isAjax()) {
                $this->getResponse()->representJson(
                    $this->_objectManager->get('Magento\Framework\Json\Helper\Data')->jsonEncode([
                        'backUrl' => $this->_redirect->getRedirectUrl()
                    ])
                );
                return;
            }
            $resultRedirect = $this->resultRedirectFactory->create();
            $resultRedirect->setRefererOrBaseUrl();
            return $resultRedirect;
        }
 
        // Prepare helper and params
        $params = new \Magento\Framework\DataObject();
        $params->setCategoryId($categoryId);
        $params->setSpecifyOptions($specifyOptions);
 
        // Render page
        try {
            $page = $this->resultPageFactory->create(false, ['isIsolated' => true]);
            $this->viewHelper->prepareAndRender($page, $productId, $this, $params);
            return $page;
        } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
            return $this->noProductRedirect();
        } catch (\Exception $e) {
            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
            $resultForward = $this->resultForwardFactory->create();
            $resultForward->forward('noroute');
            return $resultForward;
        }
    }    
}
?>

协助

app/code/Mageplaza/HelloWorld/etc/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">
    <preference for="Magento\Catalog\Helper\Data" type="Mageplaza\HelloWorld\Helper\Catalog\Data" />
</config>

那时,您可以重写getProduct()class的功能Magento\Catalog\Helper\Data,那么您只需在var/log/debug.log此测试中登录一些消息即可。

app/code/Mageplaza/HelloWorld/Helper/Catalog/Data.php

<?php
 
namespace Mageplaza\HelloWorld\Helper\Catalog;
 
class Data extends \Magento\Catalog\Helper\Data
{    
    /**
     * Retrieve current Product object
     *
     * @return \Magento\Catalog\Model\Product|null
     */
    public function getProduct()
    {
        // logging to test override    
        $logger = \Magento\Framework\App\ObjectManager::getInstance()->get('\Psr\Log\LoggerInterface');
        $logger->debug('Helper Override Test');
        
        return $this->_coreRegistry->registry('current_product');
    }
}
?>

但是,如果两个或多个模块尝试重写同一核心类,则该首选项可能会造成不便的冲突。

如果您仍然遇到任何麻烦,请对此主题发表评论,我们将尽快为您提供帮助。

相关文章

0 0 投票数
文章评分
订阅评论
提醒
0 评论
内联反馈
查看所有评论