greg0ire / enum
解决PHP中缺少枚举类型的问题
Requires
- php: ^7.1 || ^8.0
- doctrine/inflector: ^1.4 || ^2.0
Requires (Dev)
- matthiasnoback/symfony-dependency-injection-test: ^4.0
- symfony/config: ^4.2 || ^5.0 || ^6.0
- symfony/dependency-injection: ^4.2 || ^5.0 || ^6.0
- symfony/form: ^4.2.5 || ^5.0 || ^6.0
- symfony/framework-bundle: ^4.2 || ^5.0 || ^6.0
- symfony/http-kernel: ^4.2 || ^5.1.5 || ^6.0
- symfony/options-resolver: ^4.2 || ^5.0 || ^6.0
- symfony/phpunit-bridge: ^5.0 || ^6.0
- symfony/translation: ^4.2 || ^5.0 || ^6.0
- symfony/translation-contracts: ^2.0
- symfony/twig-bundle: ^4.2 || ^5.0 || ^6.0
- symfony/validator: ^4.3.6 || ^5.0 || ^6.0
- twig/twig: ^2.4.2 || ^3.0
Suggests
- symfony/form: To use enum form type
- symfony/validator: To use enum validator
Conflicts
- symfony/form: <3.2 || >=7.0 <999
- symfony/validator: <3.2 || >=7.0 <999
README
此包包含一个简单的类,可以作为您的枚举类基类使用。
安装
composer require greg0ire/enum
使用方法
基本使用
扩展 Greg0ire\Enum\AbstractEnum
,将您的枚举键值定义为常量,然后Bob就是你的叔叔。您可以使其类为抽象的或最终的,按需而定。
use Greg0ire\Enum\AbstractEnum; final class DaysOfWeek extends AbstractEnum { const Sunday = 0; const Monday = 1; const Tuesday = 2; const Wednesday = 3; const Thursday = 4; const Friday = 5; const Saturday = 6; }
然后,您可以使用 DaysOfWeek 类进行输入验证
DaysOfWeek::isValidName('Humpday'); // false DaysOfWeek::isValidName('Monday'); // true DaysOfWeek::isValidName('monday'); // false DaysOfWeek::isValidName(0); // false DaysOfWeek::isValidValue(0); // true DaysOfWeek::isValidValue(5); // true DaysOfWeek::isValidValue(7); // false DaysOfWeek::isValidValue('Friday'); // false
这两种方法都有一个 assert*
对应方法,将抛出 Greg0ire\Enum\Exception\InvalidEnumValue
异常
DaysOfWeek::assertValidName(0); // InvalidEnumName
DaysOfWeek::assertValidValue('Friday'); // InvalidEnumValue
此外,您还可以将类中的所有常量作为哈希表获取
DaysOfWeek::getConstants(); DaysOfWeek::getConstants('strtolower'); // Will combine your values with `DaysOfWeek::getKeys($callback)`. DaysOfWeek::getConstants('strtolower', true); // Values combine with `DaysOfWeek::getClassPrefixedKeys($callback)`. DaysOfWeek::getConstants('strtolower', true, '.'); // Same with `DaysOfWeek::getClassPrefixedKeys($callback, $separator)`.
您还可以获取类中的所有键作为数组
DaysOfWeek::getKeys(); DaysOfWeek::getKeys('strtolower'); // Will call `array_map` with the given callback.
或带有枚举类前缀的键
DaysOfWeek::getClassPrefixedKeys(); DaysOfWeek::getClassPrefixedKeys('strtolower'); // Will call `array_map` with the given callback. DaysOfWeek::getClassPrefixedKeys('strtolower', '.'); // Replace the namespace separator ('_' by default).
如果您想从值获取键
$key = DaysOfWeek::getKeysFromValue(1); // Monday will be assigned to $key
如果您有许多具有相同值的键,您将获得一个数组,否则将获得一个值。
高级使用
如果您需要从无法修改的类中获取常量,或从接口中获取,或从多个类/接口中获取,您可能需要覆盖 AbstractEnum::getEnumTypes()
。
例如,如果您有以下类和接口
namespace Vendor\Namespace; class ClassFromAVendor { const SOMETHING = 'something'; const SOMETHING_ELSE = 'something_else'; }
namespace My\Namespace; interface SomeInterface { const ANOTHER_CONST = 'another_const'; }
您可以通过创建此枚举来获取所有三个常量
use Greg0ire\Enum\AbstractEnum; use My\Namespace\SomeInterface; use Vendor\Namespace\ClassFromAVendor; final class MyEnum extends AbstractEnum { protected static function getEnumTypes() { return [ClassFromAVendor::class, SomeInterface::class]; } }
或者,您可以为每个类型指定一个前缀,以避免在哈希键中获取完全限定类名。
use Greg0ire\Enum\AbstractEnum; use My\Namespace\SomeInterface; use Vendor\Namespace\ClassFromAVendor; final class MyEnum extends AbstractEnum { protected static function getEnumTypes() { return [ 'prefix1' => ClassFromAVendor::class, 'prefix2' => SomeInterface::class, ]; } }
从服务获取标签
如果您想获取枚举值背后的常量标签,可以实例化 GetLabel
类并调用它。
use Greg0ire\Enum\Bridge\Symfony\Translator\GetLabel; $label = new GetLabel(); $label(Your\Enum\Class::VALUE, Your\Enum\Class::class);
要启用翻译,需要 symfony/translation
组件,并在 GetLabel
构造函数中传递一个 Symfony\Contracts\Translation\TranslationInterface
实例。
use Greg0ire\Enum\Bridge\Symfony\Translator\GetLabel; use Symfony\Contracts\Translation\TranslationInterface; $label = new GetLabel($translator); $label(Your\Enum\Class::VALUE, Your\Enum\Class::class);
如果您使用 Symfony,别名服务并简单地注入它。如果启用了翻译,则将自动注入 TranslatorInterface
。
services: # ... Greg0ire\Enum\Bridge\Symfony\Translator\GetLabel: "@greg0ire_enum.symfony.translator.get_label"
public function index(GetLabel $label) { $label(Your\Enum\Class::VALUE, Your\Enum\Class::class); $label(Your\Enum\Class::VALUE, Your\Enum\Class::class, 'another_domain'); // Change the translation domain $label(Your\Enum\Class::VALUE, Your\Enum\Class::class, false); // Disable translation. In this case the class prefix wont be added $label(Your\Enum\Class::VALUE, Your\Enum\Class::class, false, true); // Disable translation but keep class prefix $label(Your\Enum\Class::VALUE, Your\Enum\Class::class, false, true, '.'); // Disable translation but keep class prefix with a custom separator }
与其他库的集成
greg0ire/enum
与其他库集成。列表可在 Composer 依赖项清单的 suggest
部分找到。
Symfony 验证器
此包提供了一个“即用型”的 symfony 验证器。您需要安装 symfony/validator
包才能使用它。
use Greg0ire\Enum\Bridge\Symfony\Validator\Constraint\Enum; use Symfony\Component\Validator\Validation; use Your\Namespace\EnumClass; $validator = Validation::createValidator(); $violations = $validator->validateValue(42, new Enum(EnumClass::class)); // You can also show the constants keys on the error message: $violations = $validator->validateValue(42, new Enum(['class' => EnumClass::class, 'showKeys' => true])); // Enum constraint inherits from Choice constraint. You can use inherited options too: $violations = $validator->validateValue(42, new Enum(['class' => EnumClass::class, 'strict' => true]));
带有注解的另一个示例
use Doctrine\Common\Annotations\AnnotationRegistry; use Greg0ire\Enum\Bridge\Symfony\Validator\Constraint\Enum as EnumAssert; use Symfony\Component\Validator\Validation; class MyClass { /** * @EnumAssert("Your\Namespace\EnumClass") */ private $dummy; public function __construct($dummy) { $this->dummy = $dummy } } AnnotationRegistry::registerLoader('class_exists'); $validator = Validation::createValidatorBuilder() ->enableAnnotationMapping() ->getValidator(); $object = new MyClass(42); $violations = $validator->validate($object);
注意:您将需要获取 doctrine/annotations
和 doctrine/cache
包才能使用它。
Symfony 表单
此包提供了一个“即用型”的 symfony 表单类型。您需要安装 symfony/form
包才能使用它。
use Greg0ire\Enum\Bridge\Symfony\Form\Type\EnumType; use Symfony\Component\Form\Forms; use Your\Namespace\EnumClass; $formFactory = Forms::createFormFactory(); $view = $this->factory->create(EnumType::class, null, array( 'class' => EnumClass::class, ))->createView();
Twig 扩展
此包附带一个 EnumExtension
Twig 类。它包含一个过滤器和一些函数。您需要安装 twig/twig
包才能使用它。
过滤器
enum_label
过滤器将尝试返回对应于给定值的常量标签。
此过滤器依赖于 Greg0ire\Enum\Bridge\Symfony\Translator\GetLabel
服务。
如果可能,它将尝试将其翻译。要启用翻译,需要 symfony/translation
组件,并在 GetLabel
构造函数中传递一个 Symfony\Contracts\Translation\TranslationInterface
实例。GetLabel
实例将在 EnumExtension
构造函数中注入。
如果翻译不可用,您将获得具有类前缀的默认标签。
使用方法
{{ value|enum_label('Your\\Enum\\Class') }} {{ value|enum_label('Your\\Enum\\Class', 'another_domain') }} {# Change the translation domain #} {{ value|enum_label('Your\\Enum\\Class', false) }} {# Disable translation. In this case the class prefix wont be added #} {{ value|enum_label('Your\\Enum\\Class', false, true) }} {# Disable translation but keep class prefix #} {{ value|enum_label('Your\\Enum\\Class', false, true, '.') }} {# Disable translation but keep class prefix with a custom separator #}
函数
3 个可用的 twig 函数是某些 AbstractEnum
方法,在 twig 模板中可能很有用
enum_get_constants
<=>AbstractEnum::getConstants
enum_get_keys
<=>AbstractEnum::getKeys
enum_get_class_prefixed_keys
<=>AbstractEnum::getClassPrefixedKeys
参数完全相同,只是你需要先指定目标类(例如作为 enum_label
过滤器)。
以下是一个使用 enum_get_constants
函数的具体示例
{% for enum_key, enum_value in enum_get_constants('Your\\Enum\\Class') %} {{ enum_key }} -> {{ enum_value }} {% endfor %}
作为服务的Twig扩展
在Symfony项目中,该扩展可以被自动加载。首先,你需要引入 symfony/framework-bundle
和 symfony/twig-bundle
包,或者使用Symfony全栈。
然后,在你的应用程序内核中注册该包
// app/AppKernel.php public function registerBundles() { $bundles = [ // ... new Greg0ire\Enum\Bridge\Symfony\Bundle\Greg0ireEnumBundle(), ]; // ... return $bundles }
这就完了。现在你可以直接使用过滤器了。
贡献
请参阅 CONTRIBUTING.md
鸣谢
这是一个无耻的剽窃自 这个Stack Overflow答案,有一个修改:将 getConstants
方法设为公共,以便它可以用于构建选择小部件等。如果你想要感谢某个人,请感谢 Brian Cline