algo26-matthias/idna-convert
PHP library for converting internationalized domain names between Unicode and Punycode. Implements IDNA 2003 and UTS #46 (IDNA 2008) standards with configurable encoding and decoding options. A mature, standalone package compatible with PHP 5.3 through 8.x and used by phpMyAdmin.
Architecture fit. This is a narrow, stateless, pure-PHP value converter — a single class with convert()/toAscii()/toUnicode() semantics. There is no service surface, no config, no persistence, no async work. In a Laravel codebase that makes it trivially composable and trivially replaceable, which is the right shape for a dependency of this risk profile. Its only genuine architectural claim is that it does IDNA without ext-intl; on standard Forge/Vapor/Docker/Valet images ext-intl is present, so the package is likely redundant against idn_to_ascii(..., IDNA_NONTRANSITIONAL_TO_ASCII) or symfony/polyfill-intl-idn. A TPM should require a written justification for why the built-in path is insufficient before approving it.
Integration feasibility. High. Composer-installable, no extension requirements, no Laravel version coupling, no publishable assets. First check whether it is already in the tree transitively (composer why algo26-matthias/idna-convert) — email-validation dependency chains have historically pulled IDNA converters in, and "already shipped" materially changes the risk conversation from new dependency to existing exposure we should now track.
Technical risk.
Key questions. Which Unicode version are the tables built against? Does it implement IDNA2008 + UTS#46 non-transitional, and does it pass the official IdnaTestV2.txt vectors? What is the PHP version support matrix and is there static analysis/CI? Does malformed input throw or return false, and is that contract documented? Who is the maintainer, what is the response time on security reports, and where is the canonical repo? Is the package already transitive in our lockfile? What is the fallback if it is abandoned tomorrow?
Stack fit. Good but conditional. Auto-discovery is irrelevant (no provider needed), no config publishing, no migrations. It coexists cleanly with symfony/polyfill-intl-idn because it is namespaced classes rather than global function shims — no collision risk. The blocking question is deployment environment: if ext-intl is available everywhere you deploy, this package adds dependency surface for zero functional gain.
Migration path. Do not call the vendor class from controllers, form requests, or custom validation rules. Introduce an application-owned seam first:
App\Support\Contracts\IdnConverter with toAscii(string): string and toUnicode(string): string.IntlIdnConverter (ext-intl) and PolyfillIdnConverter (Symfony polyfill). Bind via a service provider with an env/config switch.IdnaConvertAdapter as a third implementation if you have a concrete environment without ext-intl.This makes adoption (and reversal) a one-line config change and keeps the vendor surface to a single file.
Compatibility. Effectively unconstrained on the Laravel side (10/11/12 all fine). Real constraints are PHP version floor, whether the package lags current PHP releases, and whether it conflicts with any transitive IDNA dependency already resolved. Pin exactly and commit the lockfile; avoid floating constraints given provenance uncertainty.
Sequencing.
composer why.idn_to_ascii().Maintenance. Low day-to-day touch (nothing to operate), high latent ownership. If the maintainer disappears you inherit the library, and LGPL-2.1 permits that — budget an explicit fork-and-maintain contingency and record it in the dependency register with a named owner. Re-review on every Unicode release and every PHP minor upgrade. This is a "review annually, don't think about it otherwise" dependency, not a "monitor weekly" one.
Support. No vendor, no SLA, no paid tier. Escalation path is "we read the source and patch it," which is only credible if someone on the team can read it — which loops back to the provenance problem: with no verifiable repo, even filing an upstream issue has no confirmed destination. Set stakeholder expectations accordingly: this is community-supported at best.
Scaling. Negligible. String transformation, no I/O, no external calls, no memory retention, no pool exhaustion. Per-call cost is microseconds to low milliseconds; at one conversion per inbound request it will never appear on a profile. The one real hazard is bulk paths — importing domains, normalizing an email list, mail-merge addressing — where per-call cost multiplies into minutes. Memoize normalized results in a cache keyed by input hash, and never call the converter inside a tight loop over already-normalized data.
Failure modes.
Ramp-up. Near zero for the average engineer: one class, two methods, done in ten minutes. The real cost is domain literacy — IDNA2008 vs IDNA2003, transitional vs non-transitional processing, and why a "valid" conversion isn't a safe one. Assign one engineer as owner of DNS/email normalization semantics, and write a short ADR recording which IDNA profile you standardize on and why this package was chosen over ext-intl. That ADR is the artifact that makes the next maintainer's decision cheap and this one defensible.
How can I help you explore Laravel packages today?