{"record":{"id":"eda07d76a6348fe5","repo":"pestphp/pest","slug":"the-s-feature-requires-s-please-install-it","errorCode":null,"errorMessage":"The [%s] feature requires [%s]. Please install it and try again.","messagePattern":"The \\[(.+?)\\] feature requires \\[(.+?)\\]\\. Please install it and try again\\.","errorType":"exception","errorClass":"MissingDependency","httpStatus":null,"severity":"error","filePath":"src/Expectations/OppositeExpectation.php","lineNumber":244,"sourceCode":"\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => array_filter(\n                $methods,\n                fn (string $method): bool => isset($object->reflectionClass) === false || $object->reflectionClass->hasMethod($method),\n            ) === [],\n            'to not have methods: '.implode(', ', $methods),\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    public function toHaveSuspiciousCharacters(): ArchExpectation\n    {\n        if (! class_exists(Spoofchecker::class)) {\n            throw new MissingDependency(__FUNCTION__, 'ext-intl >= 2.0');\n        }\n\n        $checker = new Spoofchecker;\n\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => ! $checker->isSuspicious((string) file_get_contents($object->path)),\n            'to not include suspicious characters',\n            FileLineFinder::where(fn (string $line): bool => $checker->isSuspicious($line)),\n        );\n    }\n\n    /**\n     * @param  array<int, string>  $methods\n     */","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/pestphp/pest/blob/1af74a215c3a89bc7a44fc6f9322e369eaad2423/src/Expectations/OppositeExpectation.php#L226-L262","documentation":"The toHaveSuspiciousCharacters arch expectation (including its negated form) relies on Spoofchecker from PHP's intl extension (ext-intl >= 2.0) to detect confusable/homoglyph identifiers. Pest checks class_exists(Spoofchecker::class) first and throws MissingDependency — 'The [toHaveSuspiciousCharacters] feature requires [ext-intl >= 2.0]. Please install it and try again.' — before scanning any file.","triggerScenarios":"Running an architecture test that calls ->toHaveSuspiciousCharacters() or ->not->toHaveSuspiciousCharacters() on a PHP build compiled without intl; slim Docker images (alpine, php:*-cli) that ship without ext-intl; CI matrices where only some jobs install intl.","commonSituations":"Local macOS/Linux PHP built with --disable-intl; Alpine docker images requiring docker-php-ext-install intl; shared hosts where the extension is present but not enabled in php.ini; enabling spoof-checking rules in a shared arch pest file that all environments run.","solutions":["Install and enable ext-intl: docker-php-ext-install intl (plus icu-dev on Alpine), apt install php-intl (Debian/Ubuntu), brew install php (macOS), then restart PHP/CI runner.","Enable an already-installed extension: uncomment extension=intl in php.ini and confirm with php -m | grep intl.","If intl cannot be installed in that environment, remove or skip the toHaveSuspiciousCharacters expectation (mark it skipped when extension_loaded('intl') is false)."],"exampleFix":"# before (Dockerfile)\nFROM php:8.3-cli\n# vendor/bin/pest --tests arch -> MissingDependency\n# after\nFROM php:8.3-cli\nRUN apt-get update && apt-get install -y libicu-dev \\\n    && docker-php-ext-install intl","handlingStrategy":"validation","validationCode":"if (! extension_loaded('intl') || ! class_exists(Spoofchecker::class)) {\n    test('arch: no suspicious characters')\n        ->skip(! extension_loaded('intl'), 'ext-intl not installed');\n}\n// or guard before running the suite at all:\nif (! extension_loaded('intl')) {\n    fwrite(STDERR, \"ext-intl is required for spoof-checking arch tests\\n\");\n    exit(1);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Declare ext-intl in composer.json require-dev so Composer fails early when it is absent.","Bake ext-intl into Docker images and CI matrices (docker-php-ext-install intl, apt install php-intl).","Verify with php -m | grep intl in CI bootstrap when arch tests use Spoofchecker."],"tags":["pest","arch","ext-intl","missing-dependency","php-extension","docker"],"backgroundTag":"missing-php-extension","analyzedSha":"1af74a215c3a89bc7a44fc6f9322e369eaad2423","analyzedAt":"2026-08-21T02:16:38.132Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}