如何不修改核心类扩展Botble ShippingStatusEnum添加新常量
问题:扩展Laravel电商系统的配送状态枚举(不修改核心文件)
我正在为基于Laravel的电商系统开发自定义插件,系统使用核心类ShippingStatusEnum管理配送状态。需要添加新状态in_transit(运输中),但不能修改原始核心枚举文件。
尝试创建了扩展类,但调用ShippingStatusEnum时新状态不显示。
自己编写的扩展类代码:
namespace Botble\OrderManagement\Enums; use Botble\Ecommerce\Enums\ShippingStatusEnum; use Botble\Base\Facades\BaseHelper; use Illuminate\Support\HtmlString; class ExtendedShippingStatusEnum extends ShippingStatusEnum { public const IN_TRANSIT = 'in_transit'; public function toHtml(): HtmlString|string { $color = match ($this->value) { self::IN_TRANSIT => 'primary', default => parent::toHtml(), }; return BaseHelper::renderBadge($this->label(), $color); } }
核心ShippingStatusEnum.php代码:
<?php namespace Botble\Ecommerce\Enums; use Botble\Base\Facades\BaseHelper; use Botble\Base\Supports\Enum; use Illuminate\Support\HtmlString; class ShippingStatusEnum extends Enum { public const NOT_APPROVED = 'not_approved'; public const APPROVED = 'approved'; public const PENDING = 'pending'; public const ARRANGE_SHIPMENT = 'arrange_shipment'; public const READY_TO_BE_SHIPPED_OUT = 'ready_to_be_shipped_out'; public const PICKING = 'picking'; public const DELAY_PICKING = 'delay_picking'; public const PICKED = 'picked'; public const NOT_PICKED = 'not_picked'; public const DELIVERING = 'delivering'; public const DELIVERED = 'delivered'; public const NOT_DELIVERED = 'not_delivered'; public const AUDITED = 'audited'; public const CANCELED = 'canceled'; public static $langPath = 'plugins/ecommerce::shipping.statuses'; public function toHtml(): HtmlString|string { $color = match ($this->value) { self::NOT_APPROVED, self::PENDING, self::DELAY_PICKING, self::APPROVED => 'warning', self::PICKING, self::READY_TO_BE_SHIPPED_OUT, self::DELIVERING, self::ARRANGE_SHIPMENT => 'info', self::NOT_PICKED, self::CANCELED, self::NOT_DELIVERED => 'danger', self::DELIVERED, self::AUDITED => 'success', default => 'primary', }; return BaseHelper::renderBadge($this->label(), $color); } }
解决方案
1. 重写枚举静态方法,合并新状态
核心Enum基类的静态方法(如toArray()、labels())只会返回自身定义的常量,子类继承后不会自动合并新增常量。需要在扩展类中重写这些方法:
修改ExtendedShippingStatusEnum,添加以下代码:
// 返回所有枚举值(含新状态) public static function toArray(): array { return array_merge(parent::toArray(), [ self::IN_TRANSIT => self::IN_TRANSIT, ]); } // 返回所有状态的标签(含新状态) public static function labels(): array { return array_merge(parent::labels(), [ self::IN_TRANSIT => __('plugins/order-management::shipping.statuses.in_transit'), ]); }
2. 添加新状态的语言文件
在你的插件目录下创建语言文件,确保标签能正确显示:
- 英文语言文件:
resources/lang/en/shipping/statuses.php
<?php return [ 'in_transit' => 'In Transit', ];
- 中文语言文件:
resources/lang/zh-CN/shipping/statuses.php
<?php return [ 'in_transit' => '运输中', ];
3. 让系统使用扩展后的枚举类
系统默认调用核心ShippingStatusEnum,需要通过以下方式替换:
方式一:全局替换(服务容器绑定)
在插件的boot()方法中添加绑定逻辑,让系统全局使用你的扩展类:
use Botble\Ecommerce\Enums\ShippingStatusEnum; use Botble\OrderManagement\Enums\ExtendedShippingStatusEnum; public function boot() { $this->app->bind(ShippingStatusEnum::class, function () { return ExtendedShippingStatusEnum::class; }); }
方式二:局部替换
在你自己的插件代码中,直接使用ExtendedShippingStatusEnum代替核心类,比如:
use Botble\OrderManagement\Enums\ExtendedShippingStatusEnum; // 获取所有配送状态 $allStatuses = ExtendedShippingStatusEnum::labels(); // 创建新状态实例 $inTransitStatus = ExtendedShippingStatusEnum::from('in_transit');
4. 修复toHtml()方法的逻辑错误
原扩展类的toHtml()方法存在逻辑问题:默认分支直接返回parent::toHtml(),会导致重复渲染徽章。正确写法是复用父类的颜色判断逻辑,添加新状态的规则:
public function toHtml(): HtmlString|string { $color = match ($this->value) { self::IN_TRANSIT => 'primary', self::NOT_APPROVED, self::PENDING, self::DELAY_PICKING, self::APPROVED => 'warning', self::PICKING, self::READY_TO_BE_SHIPPED_OUT, self::DELIVERING, self::ARRANGE_SHIPMENT => 'info', self::NOT_PICKED, self::CANCELED, self::NOT_DELIVERED => 'danger', self::DELIVERED, self::AUDITED => 'success', default => 'primary', }; return BaseHelper::renderBadge($this->label(), $color); }
5. 清除系统缓存
修改枚举后,执行以下命令清除Laravel缓存,确保新状态生效:
php artisan cache:clear php artisan config:clear php artisan view:clear
内容的提问来源于stack exchange,提问作者Amine Amine
相关产品推荐
相关产品推荐

