ekvedaras / php-enum
PHP 枚举实现
Requires
- php: >=7.2
- ext-json: *
Requires (Dev)
- doctrine/collections: ^1.6
- illuminate/support: ^6|^7|^8
- phpunit/phpunit: ^8.5.8
- voku/arrayy: ^7.0
Suggests
- doctrine/collections: Required for \EKvedaras\PHPEnum\Doctrine\Enum implementation
- illuminate/collections: Required for \EKvedaras\PHPEnum\Illuminate\Collection\Enum implementation. Provides standalone Laravel collections
- illuminate/support: Required for \EKvedaras\PHPEnum\Illuminate\Collection\Enum implementation. Use if illuminate/collections can't be installed due to version contstraints
- voku/arrayy: Required for \EKvedaras\PHPEnum\Arrayy\Enum implementation
README
非常感谢happy-types/enumerable-type的原始想法。如果您需要更好的解决方案,请查看。
此包添加了meta字段,提供了一些额外的方法,如options、keys、json等,并且有简单的php数组、illuminate/collection、arrayy和doctrine集合实现可供选择。
优势
- 枚举通常可以避免魔法值
- 通过类型提示强制将仅允许的值传递给方法(或返回)
- 列出所有可能值的一种简单方法
- 比其他枚举实现更丰富和灵活
- 与严格的(
===)运算符一起工作 - IDE友好,因此自动完成、使用分析和重构都可以工作
定义枚举
通过扩展以下之一来创建枚举
EKvedaras\PHPEnum\PHPArray\EnumEKvedaras\PHPEnum\Illuminate\Collection\EnumEKvedaras\PHPEnum\Arrayy\EnumEKvedaras\PHPEnum\Doctrine\Enum
use EKvedaras\PHPEnum\PHPArray\Enum; class PaymentStatus extends Enum { /** * @return static */ final public static function pending(): self { return static::get('pending', 'Payment is pending'); } /** * @return static */ final public static function completed(): self { return static::get('completed', 'Payment has been processed'); } /** * @return static */ final public static function failed(): self { return static::get('failed', 'Payment has failed'); } }
如果您喜欢,可以使用整数作为ID而不是字符串值。
用法
检索和比较枚举值
// Retrieving value statically $status1 = PaymentStatus::completed(); // Retrieving value dynamically from ID $status2 = PaymentStatus::from('completed'); // Strict comparison is supported var_dump($status1 === $status2); // true
访问值属性
$status = PaymentStatus::copmleted(); $status->id(); // 'completed' $status->name(); // 'Payment has been processed' $status->meta(); // null
列出枚举值
提供了两种实现
PHP数组
要使用PHP数组,您的枚举应扩展EKvedaras\PHPEnum\PHPArray\Enum类
var_dump(PaymentStatus::enum()); /* array(3) { 'pending' => class PaymentStatus#12 (3) { protected $id => string(7) "pending" protected $name => string(18) "Payment is pending" protected $meta => NULL } 'completed' => class PaymentStatus#363 (3) { protected $id => string(9) "completed" protected $name => string(26) "Payment has been processed" protected $meta => NULL } 'failed' => class PaymentStatus#13 (3) { protected $id => string(6) "failed" protected $name => string(18) "Payment has failed" protected $meta => NULL } } */
var_dump(PaymentStatus::options()); /* array(3) { 'pending' => string(18) "Payment is pending" 'completed' => string(26) "Payment has been processed" 'failed' => string(18) "Payment has failed" } */
var_dump(PaymentStatus::keys()); /* array(3) { [0] => string(7) "pending" [1] => string(9) "completed" [2] => string(6) "failed" } */
var_dump(PaymentStatus::json()); // Will include meta if defined
{
"pending": {
"id": "pending",
"name": "Payment is pending"
},
"completed": {
"id": "completed",
"name": "Payment has been processed"
},
"failed": {
"id": "failed",
"name": "Payment has failed"
}
}
var_dump(PaymentStatus::jsonOptions());
{
"pending": "Payment is pending",
"completed": "Payment has been processed",
"failed": "Payment has failed"
}
Illuminate Collection
需要illuminate/support或illuminate/collections包,该包默认未安装。
要使用Illuminate Collection,您的枚举应扩展EKvedaras\PHPEnum\Illuminate\Collection\Enum类。
唯一的区别是enum、options和keys方法将返回Collection实例而不是数组。其余部分工作方式完全相同。
var_dump(PaymentStatus::enum()); /* class Illuminate\Support\Collection#362 (1) { protected $items => array(3) { 'pending' => class PaymentStatus#12 (3) { protected $id => string(7) "pending" protected $name => string(18) "Payment is pending" protected $meta => NULL } 'completed' => class PaymentStatus#363 (3) { protected $id => string(9) "completed" protected $name => string(26) "Payment has been processed" protected $meta => NULL } 'failed' => class PaymentStatus#13 (3) { protected $id => string(6) "failed" protected $name => string(18) "Payment has failed" protected $meta => NULL } } } */
var_dump(PaymentStatus::options()); /* class Illuminate\Support\Collection#368 (1) { protected $items => array(3) { 'pending' => string(18) "Payment is pending" 'completed' => string(26) "Payment has been processed" 'failed' => string(18) "Payment has failed" } } */
var_dump(PaymentStatus::keys()); /* class Illuminate\Support\Collection#13 (1) { protected $items => array(3) { [0] => string(7) "pending" [1] => string(9) "completed" [2] => string(6) "failed" } } */
元数据
元数据字段有意保留为混合类型,因为它可以用于各种原因。例如,将枚举选项与特定实现相关联
use EKvedaras\PHPEnum\PHPArray\Enum; class PaymentMethod extends Enum { final public static function payPal(): self { return static::get('paypal', 'PayPal', PayPalHandler::class); } final public static function stripe(): self { return static::get('stripe', 'Stripe', StripeHandler::class); } }
在Laravel中解决支付处理器
$method = PaymentMethod::from($request['method_id']); $handler = app($method->meta());
元数据也可以用作每个选项的更详细描述,可以显示给用户或链接其他类的某些其他对象。
此外,在某些情况下,从元数据中解决枚举选项很有用。这也是可能的
$method = PaymentMethod::fromMeta(StripeHandler::class);
需要注意的事项
final public static function
只有标记为final public static的方法才会被视为枚举的可能值。其他方法仍然存在,但它们不会在enum / keys / options等结果中返回,也不会被视为有效值。然而,这允许扩展枚举并使其更有用。例如
use EKvedaras\PHPEnum\Illuminate\Collection\Enum; use Illuminate\Support\Collection; class PaymentMethods extends Enum { /** * @return static */ final public static function payPal(): self { return static::get('paypal', 'PayPal'); } /** * @return static */ final public static function stripe(): self { return static::get('stripe', 'Stripe'); } /** * @return static */ final public static function mollie(): self { return static::get('mollie', 'Mollie'); } /** * Returns only enabled payment methods. Useful for validation or rendering payments UI * @return Collection|static[] */ public static function enabled(): Collection { return static::enum()->only(config('payments.enabled')); } }
from($id)仅允许有效的ID
嗯,这是预期的。调用PaymentMethod::from('ideal')将抛出OutOfBoundsException。
不可序列化
枚举对象实例不能序列化。反序列化对象会在内存中获得不同的地址,因此,===将不再工作。调用serialize(PaymentMethod::stripe())将抛出RuntimeException。
作为解决方案,最好存储ID而不是对象本身。您仍然可以获得仅接受有效值的设置器的额外好处。
class Payment { /** @var string */ private $method; public function setMethod(PaymentMethod $method) { $this->method = $method->id(); } public function getMethod(): PaymentMethod { return PaymentMethod::from($this->method); } }
不要混合实现
枚举实例缓存存储在静态变量中。为您的项目选择一个实现并坚持使用它,否则您可能会意外地遇到由于类型不匹配而引起的错误。
您可以创建自己的项目枚举类,并扩展您选择的实现,这样如果需要更改,只需在一个地方进行(如果存储API匹配)。
相关包
变更日志
查看变更日志文件中的更改