Magento2.3.5学习重写核心类

        在Magento 2中,重写(Override)核心类的方法通常有三种:通过插件(Plugin)、通过依赖注入(Preference)、和通过事件观察者(Event Observer)。每种方法适用于不同的场景,以下是对这三种方法的详细说明和使用方式。

        例如要重写Product类可以通过这三种方式来实现

1. 插件(Plugin)

插件也被称为“拦截器”,是Magento 2推荐的重写方法。通过插件可以在原方法执行前后或者绕过原方法来添加自定义逻辑,而不会影响原始方法的实现。

插件使用步骤

1.创建 di.xml 配置文件:

  • 在 app/code/Vendor/HelloWorld/etc/di.xml 中添加插件配置:
    <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="vendor_helloworld_product_plugin" type="Vendor\HelloWorld\Plugin\ProductPlugin" sortOrder="10" disabled="false" />
        </type>
    </config>
    
  • type:要重写的类(目标类),如 Magento\Catalog\Model\Product
  • plugin name:插件的名称,命名需唯一。
  • type:自定义插件类的路径。

2.创建插件类

  • 在 app/code/Vendor/HelloWorld/Plugin/ProductPlugin.php 中创建插件类:
    <?php
    namespace Vendor\HelloWorld\Plugin;
    
    use Magento\Catalog\Model\Product;
    use Psr\Log\LoggerInterface;
    
    class ProductPlugin
    {
        protected $logger;
        public function __construct(LoggerInterface $logger)
        {
            $this->logger = $logger;
        }
    
        public function beforeSave(Product $subject)
        {
            $name = $subject->getName();
            $subject->setName(strtoupper($name));
        }
    
        public function afterSave(Product $subject, $result)
        {
            $id = $subject->getId();
            if ($id) {
                $this->logger->info('Product Plugin saved with ID: ' . $id);
            } else {
                $this->logger->info('Nothing');
            }
    
            return $result;
        }
    
        public function aroundSave(Product $subject, callable $proceed)
        {
            $name = $subject->getName();
    
            $subject->setName('Before Save: ' . $name);
            $result = $proceed();
    
            $id = $subject->getId();
            $product = $subject->load($id);
            $new_name = $product->getName();
    
            $this->logger->info('Set New Name over saved with new name: ' . $new_name);
    
            return $result;
        }
    }
    
  • beforeSave方法:在目标方法执行之前触发,获取创建商品的名称,并且将名称进行大小写修改
  • afterSave方法:在目标方法执行之后触发,并可以修改返回结果,获取创建商品的id编号,然后将存储记录通过log保存到日志中
  • aroundSave方法:可以控制目标方法的执行流程,并决定是否调用原方法,在保存之前获取商品的名称,并且将商品的名称加上前缀,然后执行保存原方法,执行结束之后,获取新名称,并且将这条信息进行log记录

插件适用场景

  • 想在不修改原始代码的情况下对某个类的方法进行增强或修改。
  • 插件机制能够减少代码耦合,适合用于重写模型类、服务类、Block类中的方法。

2. 依赖注入(Preference)

        依赖注入是一种直接替换类的方式,适用于完全重写类的场景,但不推荐用来重写大部分逻辑复杂的类,因为这种方式会完全替换原类,可能带来兼容性问题。

Preference 使用步骤

1.创建 di.xml 配置文件:

  • 在 app/code/Vendor/HelloWorld/etc/di.xml 中添加插件配置:
    <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="Vendor\HelloWorld\Model\Rewrite\Product" />
    </config>
    
  • for:目标类名,即要替换的核心类。
  • type:替换后的自定义类。

2.创建自定义类:

  • app/code/Vendor/HelloWorld/Model/Rewrite/Product.php 中创建自定义类:
    <?php
    
    namespace Vendor\HelloWorld\Model\Rewrite;
    
    class Product extends \Magento\Catalog\Model\Product
    {
        public function getName()
        {
            // 调用父类的 getName 方法
            $name = parent::getName();
    
            // 添加自定义逻辑,例如:添加一个后缀
            return $name . ' - Custom Suffix';
        }
    
        public function getPrice()
        {
            $price = parent::getPrice();
            return $price * 0.8;
        }
    }
    
  • getName方法:通过调用父类的getName获取商品名称,并且为商品名称添加后缀
  • getPrice方法:通过调用父类的getPrice获取商品的价格,并且对商品价格进行修改

Preference 适用场景

  • 当你需要完全重写类的所有方法时使用。
  • 不推荐用于重写Magento核心模块类的方法,而更多用于自定义模块间的替换。

3. 事件观察者(Event Observer)

        事件观察者是一种基于事件机制的重写方式,可以在特定事件触发时执行自定义逻辑,而不直接修改核心类或方法。

事件观察者使用步骤

1.定义事件观察者配置文件 events.xml:

  • app/code/Vendor/HelloWorld/etc/events.xml 中添加如下配置:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <!-- 监听catalog_product_save_after事件 -->
    <event name = "catalog_product_save_after">
        <observer name = "vendor_helloworld_product_save_after_observer" instance="Vendor\HelloWorld\Observer\ProductSaveAfterObserver" />
    </event>
</config>
  • event name:要观察的事件名称。(事件名称:catalog_product_save_after)
  • observer name:观察者的名称。(观察者名称:vendor_helloworld_product_save_after_observer)
  • instance:自定义观察者类的路径。(路径:Vendor\HelloWorld\Observer\ProductSaveAfterObserver)

2.创建观察者类:

  • app/code/Vendor/HelloWorld/Observer/ProductSaveAfterObserver.php 中创建观察者类:
<?php

namespace Vendor\Helloworld\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Psr\Log\LoggerInterface;

class ProductSaveAfterObserver implements ObserverInterface
{
    protected $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function execute(Observer $observer)
    {
        // 获取保存后的产品对象
        $product = $observer->getEvent()->getProduct();

        // 在日志中记录产品ID 记录到log/system.log
        $this->logger->info('Product saved with ID: ' . $product->getId());
    }
}
  • execute() 方法中,可以通过 $observer->getEvent()->getProduct() 获取到当前事件中的 Product 对象,并对其进行操作,将Product对象的id记录到log日志里面。

事件观察者适用场景

  • 当需要在特定事件(如保存、删除等)发生时进行额外操作。
  • 事件观察者不会直接修改核心类,但能够扩展核心类行为。

4.三种重写方式的比较

方法优点缺点适用场景
插件 (Plugin)可在方法执行前后或绕过原方法,不影响原始代码复杂类重写时难以管理;某些方法无法通过插件拦截针对单个方法进行增强或修改
依赖注入 (Preference)完全替换目标类,适用于自定义模块间的替换可能导致不兼容,直接替换不安全完全替换类的实现
事件观察者 (Event Observer)基于事件的机制,能在特定操作发生时触发,便于扩展无法直接重写方法,只能进行事件相关的操作针对事件的处理,例如保存前、保存后等操作

5.具体应用场景和选择建议

  • 如果只想修改某个类中的个别方法,优先选择 插件(Plugin)。
  • 如果需要在某个事件(如保存、删除)中执行额外逻辑,使用 事件观察者(Event Observer)。
  • 如果希望完全替换某个类的实现,可以考虑 依赖注入(Preference),但要慎重使用。

效果图:

以上就是Magento2.3.5中重写核心类的三种方法,下一篇学习创建一个在magento中创建一个cron定时任务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值