PHP如何在派生类常量中使用前缀?图标常量类优化方案咨询
解决方案
方案1:利用静态魔术方法(兼容PHP 7.0+)
将图标名称统一存放在父类数组中,通过__getStatic魔术方法动态拼接前缀,无需重复定义每个图标:
abstract class Heroicon { protected const PREFIX = ""; // 统一维护所有图标名称 protected const ICONS = [ 'ACADEMIC_CAP' => 'academic-cap', 'ADJUSTMENTS' => 'adjustments', // ... 其他200+图标 ]; public static function __getStatic(string $name): ?string { return isset(static::ICONS[$name]) ? static::PREFIX . static::ICONS[$name] : null; } } class HeroiconSolid extends Heroicon { protected const PREFIX = "heroicon-s-"; } class HeroiconOutline extends Heroicon { protected const PREFIX = "heroicon-o-"; } // 使用方式(注意用$访问静态属性) echo HeroiconSolid::$ACADEMIC_CAP; // 输出 "heroicon-s-academic-cap" echo HeroiconOutline::$ADJUSTMENTS; // 输出 "heroicon-o-adjustments"
方案2:静态构造函数生成常量(PHP 8.0+)
通过PHP 8.0新增的静态构造函数,在子类加载时自动生成带前缀的常量,保持原有的常量访问方式:
abstract class Heroicon { protected const PREFIX = ""; // 统一维护所有图标名称 protected const ICONS = [ 'ACADEMIC_CAP' => 'academic-cap', 'ADJUSTMENTS' => 'adjustments', // ... 其他200+图标 ]; } class HeroiconSolid extends Heroicon { protected const PREFIX = "heroicon-s-"; public static function __constructStatic() { foreach (static::ICONS as $constName => $iconName) { // 动态定义子类常量 define(__CLASS__ . "::{$constName}", static::PREFIX . $iconName); } } } class HeroiconOutline extends Heroicon { protected const PREFIX = "heroicon-o-"; public static function __constructStatic() { foreach (static::ICONS as $constName => $iconName) { define(__CLASS__ . "::{$constName}", static::PREFIX . $iconName); } } } // 使用方式(原常量访问方式不变) echo HeroiconSolid::ACADEMIC_CAP; // 输出 "heroicon-s-academic-cap" echo HeroiconOutline::ADJUSTMENTS; // 输出 "heroicon-o-adjustments"
方案3:枚举实现(PHP 8.1+)
利用PHP 8.1的枚举特性,每个枚举对应一种图标类型,通过方法统一添加前缀:
interface HeroiconInterface { public function get(): string; } enum HeroiconSolid: string implements HeroiconInterface { case ACADEMIC_CAP = 'academic-cap'; case ADJUSTMENTS = 'adjustments'; // ... 其他200+图标 public function get(): string { return 'heroicon-s-' . $this->value; } } enum HeroiconOutline: string implements HeroiconInterface { case ACADEMIC_CAP = 'academic-cap'; case ADJUSTMENTS = 'adjustments'; // ... 其他200+图标 public function get(): string { return 'heroicon-o-' . $this->value; } } // 使用方式 echo HeroiconSolid::ACADEMIC_CAP->get(); // 输出 "heroicon-s-academic-cap" echo HeroiconOutline::ADJUSTMENTS->get(); // 输出 "heroicon-o-adjustments"
注:方案3需要手动复制图标case,但枚举自带类型校验,适合对类型安全有要求的场景;方案1和2只需在父类维护一次图标列表,更符合你避免重复代码的需求。
内容的提问来源于stack exchange,提问作者Gabor Knyihar
相关产品推荐
相关产品推荐

