prinsfrank/standards
A collection of international standards as native PHP 8.1+ enums, pulled from sources like ISO, IANA, and the US Library of Congress. Automatically updated daily so reference data such as country, currency, and language codes stays accurate, with no manual maintenance required.
Architecture fit
Integration feasibility
composer require prinsfrank/standards, one PHP version constraint, zero transitive dependencies, MIT license. A spike can be done in an afternoon and thrown away without residue.Rule::enum(), enum casts on Eloquent models, Enum::from() in form requests, ->value in API resources. The package is effectively "Laravel-ready by being framework-agnostic."tryFrom wrapping); no documentation site — the README is the API reference and it is long but dense.Technical risk
CountryAlpha3::Netherlands, CountryCallingCode::Netherlands_Kingdom_of_the. When upstream renames a territory or qualifier, the case name changes. That is a breaking change for any code that references case names, and semver allows it to ship in a major only — but it is easy to miss in review. Mitigation: ban direct case-name references in application code; use from()/tryFrom() against canonical values and serialize ->value.match without a default arm, Enum::cases() snapshot tests, and "complete list" assertions. Semver says this is fine; your CI will disagree. Treat every bump as potentially breaking until tests say otherwise.CountrySubdivision, LanguageAlpha3Extensive, and the TLD enums contain thousands of cases. Fine at autoload/opcache level for typical use; do not call ::cases() in hot paths or in Blade loops without caching.Key questions
league/iso3166, symfony/intl, Laravel's Http constants) that would create two sources of truth?Stack fit
App\Support\Standards) providing: enum validation rules, Eloquent casts, a cached cases() list provider, and normalization helpers (tryFrom on trimmed/uppercased input). This keeps library churn contained to one directory.char(2)/char(3) for country and currency codes, smallint for numeric country codes — never the case name and never a DB ENUM column. Hydrate to the enum at the boundary via cast; accept null on read for historical rows.Migration path
Enums. Rank candidates by blast radius.legacy.code === enum->value for the overlapping set in CI before cutting over.Compatibility
symfony/intl is present for formatting, keep it for formatting and this package for identity/validation, and say so in an ADR.composer.lock; use a caret range in composer.json so security/data fixes can flow, but gate merges of automated bumps behind the contract test.Sequencing and effort
Maintenance
Support
Scaling
::cases() on the large enums (CountrySubdivision, LanguageAlpha3Extensive) — memoize or move to a cached config/collection when used for dropdowns; (b) do not add these enum classes to an opcache preload list wholesale.Failure modes
| Failure | Symptom | Mitigation |
|---|---|---|
| Upstream parser breaks | Data silently stale; only a red CI badge upstream | Periodic freshness check against a known-mutable value; alerting |
| Code withdrawn/renamed upstream | ValueError from ::from(), or failed cast on hydration |
Use tryFrom() everywhere; explicit null handling; never case-name references |
Exhaustive match after minor bump |
UnhandledMatchError in production, not CI, if coverage is partial |
Default arm with logging, or strict contract test over the used set |
| Wrong minor units or symbols | Rounding/display errors in money paths | Spot-check currency table against finance's canonical list before cutover |
| Wrong calling code / TLD | SMS routing failures, validation gaps | Contract test on the specific codes in use; monitor rejection rates |
| Maintainer unavailability | No fixes for a data error | Fork plan documented and rehearsed once |
| Political/disputed naming | Market-specific compliance or PR incident | Product/legal review of exposed display names; expose codes, not names |
Ramp-up
from() vs tryFrom(), ->value vs ->name, case names being data-derived and unstable, and the rule that persisted values are scalars.PrinsFrank\Standards\*\*::SomeCaseName in application code, and a code-review note that any new match over a package enum requires a default arm.How can I help you explore Laravel packages today?