egulias/EmailValidator · error · \LogicException
The %s class requires the Intl extension.
Error message
The %s class requires the Intl extension.
What it means
SpoofCheckValidation uses the Spoofchecker class from the Intl (ICU) extension to detect visually confusable / mixed-script email addresses (a phishing technique). Its constructor throws a LogicException when extension_loaded('intl') is false, because the Spoofchecker API it calls in isValid() does not exist without that extension. Note it checks the extension itself while DNSCheckValidation checks the idn_to_ascii function — same root cause, different probe.
Source
Thrown at src/Validation/Extra/SpoofCheckValidation.php:21
namespace Egulias\EmailValidator\Validation\Extra;
use \Spoofchecker;
use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\Result\SpoofEmail;
use Egulias\EmailValidator\Result\InvalidEmail;
use Egulias\EmailValidator\Validation\EmailValidation;
class SpoofCheckValidation implements EmailValidation
{
/**
* @var InvalidEmail|null
*/
private $error;
public function __construct()
{
if (!extension_loaded('intl')) {
throw new \LogicException(sprintf('The %s class requires the Intl extension.', __CLASS__));
}
}
public function isValid(string $email, EmailLexer $emailLexer) : bool
{
$checker = new Spoofchecker();
$checker->setChecks(Spoofchecker::SINGLE_SCRIPT);
if ($checker->isSuspicious($email)) {
$this->error = new SpoofEmail();
}
return $this->error === null;
}
public function getError() : ?InvalidEmail
{
return $this->error;View on GitHub (pinned to d42c8731f0)
Solutions
- Install and enable the Intl extension: Debian/Ubuntu `apt-get install php-intl`, Alpine `apk add php83-intl`, Docker `docker-php-ext-install intl`; verify with `php -m | grep intl` in the exact SAPI (cli vs fpm) that runs your code.
- If spoof checking is a nice-to-have, gate it on extension availability: build the validation list with `extension_loaded('intl') ? new SpoofCheckValidation() : new RFCValidation()` so missing intl degrades gracefully.
- Remove SpoofCheckValidation from the validation set if the environment cannot have intl and spoof detection is not required — RFCValidation/NoRFCWarningsValidation cover syntax and RFC compliance without it.
Example fix
// before
$validations = [
new RFCValidation(),
new SpoofCheckValidation(), // throws LogicException without ext-intl
];
// after
$validations = [new RFCValidation()];
if (extension_loaded('intl')) {
$validations[] = new SpoofCheckValidation();
} Defensive patterns
Strategy: validation
Validate before calling
$validations = [new RFCValidation()];
if (extension_loaded('intl')) {
$validations[] = new SpoofCheckValidation();
}
return new MultipleValidationWithAnd($validations); Type guard
function canUseSpoofCheckValidation(): bool
{
return extension_loaded('intl') && class_exists(\Spoofchecker::class);
} Try / catch
try {
$validation = new SpoofCheckValidation();
} catch (\LogicException $e) {
// Intl extension missing: skip spoof checking rather than crashing validation
$validation = new RFCValidation();
} Prevention
- Declare `"ext-intl": "*"` in composer.json require when your app uses SpoofCheckValidation, so `composer install --ignore-platform-reqs` is the only way to end up without it.
- Gate spoof-check construction behind extension_loaded('intl') when spoof detection is optional, especially in libraries shipped to unknown hosts.
- Check `php -m | grep intl` for the web SAPI (FPM/Apache), not just CLI — a green CLI check does not prove the web server has intl loaded.
When it happens
Trigger: Instantiating `new SpoofCheckValidation()` on a PHP build without ext-intl, e.g. `new EmailValidator()->isValid($email, new SpoofCheckValidation())`. Very commonly indirect: adding spoof checking to a combined validator `new MultipleValidationWithAnd([new RFCValidation(), new SpoofCheckValidation()])` — the composite constructor itself is fine, but PHP instantiates the argument list eagerly, so the LogicException fires on the same line. Deploying with `composer install --ignore-platform-reqs` when composer.json suggests ext-intl also surfaces this only at runtime.
Common situations: Hardening an existing email validator with spoof/phishing checks on a server that never needed intl before; alpine/slim Docker base images; CI green (unit tests mock or skip it) while production throws; hosts where ext-intl exists in CLI but is disabled in the FPM/php.ini used by the web server.
Related errors
AI-assisted analysis of egulias/EmailValidator@d42c8731f0 (2026-08-21).
Data as JSON: /api/errors/379ec4bb6eed84b2.
Report an issue: GitHub.