PHPStan
phil/enumsTwo traits add methods PHPStan cannot see on its own: AsInvocableEnumTrait makes Status::DRAFT() a static
call, and AsMetadatableEnumTrait makes Status::DRAFT->label() an accessor. The library ships one extension for
each, and a rule for #[RequiredMeta], all loaded by extension.neon:
includes:
- vendor/phil/enums/extension.neon
With phpstan/extension-installer, the extra.phpstan entry of
the library's composer.json includes it automatically.
What the extensions type
InvocableEnum\ReflectionExtension: a static call named after a case of an enum that usesAsInvocableEnumTraitreturns the case's primitive — its value for a backed enum, its name for a pure one.MetadatableEnum\ReflectionExtension: an accessor named after a meta property of an enum that usesAsMetadatableEnumTraitexists, and returns the meta property's value type. The meta properties are read where the runtime reads them: the#[Meta]attribute of the enum, then that of each trait the enum uses. The return type is the property'sTValue, joined with the type of itsdefaultValue()only when some case of the enum does not carry the attribute and can therefore fall back to it.
What the rules report
RequiredMeta\RequiredMetaRule: each case of an enum that does not carry a meta property its#[RequiredMeta]attributes ask for, one error per case and property, with the identifierphilEnums.requiredMeta—Case App\Status::PUBLISHED does not carry #[Phil\Enums\Attribute\Label], which the enum requires.The errors are reported on the enum's declaration.Declaration\EnumDeclarationRule: what an enum's attributes declare wrongly, each with its identifier:Ordinal\StoredOrdinalRule(philEnums.storedOrdinal):ordinal()called on an enum withAsOrdinalEnumTraitinsidejsonSerialize(),__serialize(),normalize()orconvertToDatabaseValue()— where a value leaves the process. An ordinal changes when the cases are reordered; store the value. It is a heuristic: it knows these methods by name and follows no data flow.
The extensions and the rule read attributes by reflection and never instantiate a case, since PHPStan forbids autoloading during analysis.