{"record":{"id":"fd90afc1cb401db8","repo":"doctrine/orm","slug":"this-class-requires-php-8-4-or-higher","errorCode":null,"errorMessage":"This class requires PHP 8.4 or higher.","messagePattern":"This class requires PHP 8\\.4 or higher\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"src/Mapping/PropertyAccessors/RawValuePropertyAccessor.php","lineNumber":35,"sourceCode":" *\n * It works based on the raw values of a property, which for a case of property hooks\n * is the backed value. If we kept using setValue/getValue, this would go through the hooks,\n * which potentially change the data.\n */\nclass RawValuePropertyAccessor implements PropertyAccessor\n{\n    public static function fromReflectionProperty(ReflectionProperty $reflectionProperty): self\n    {\n        $name = $reflectionProperty->getName();\n        $key  = $reflectionProperty->isPrivate() ? \"\\0\" . ltrim($reflectionProperty->getDeclaringClass()->getName(), '\\\\') . \"\\0\" . $name : ($reflectionProperty->isProtected() ? \"\\0*\\0\" . $name : $name);\n\n        return new self($reflectionProperty, $key);\n    }\n\n    private function __construct(private ReflectionProperty $reflectionProperty, private string $key)\n    {\n        if (PHP_VERSION_ID < 80400) {\n            throw new LogicException('This class requires PHP 8.4 or higher.');\n        }\n    }\n\n    public function setValue(object $object, mixed $value): void\n    {\n        if (! ($object instanceof InternalProxy && ! $object->__isInitialized())) {\n            $this->reflectionProperty->setRawValueWithoutLazyInitialization($object, $value);\n\n            return;\n        }\n\n        $object->__setInitialized(true);\n\n        $this->reflectionProperty->setRawValue($object, $value);\n\n        $object->__setInitialized(false);\n    }\n","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/doctrine/orm/blob/d9b9ff73016bf598ae07515f97289ce8074e97a5/src/Mapping/PropertyAccessors/RawValuePropertyAccessor.php#L17-L53","documentation":"RawValuePropertyAccessor is built on ReflectionProperty::setRawValueWithoutLazyInitialization(), an API that only exists in PHP 8.4+, so its constructor guards with a PHP_VERSION_ID check and throws LogicException on older runtimes. PropertyAccessorFactory only instantiates it on PHP >= 8.4, so seeing this error means the class was instantiated directly (or a cached container/metadata built on 8.4) on an older PHP.","triggerScenarios":"Directly calling new RawValuePropertyAccessor(...) or RawValuePropertyAccessor::fromReflectionProperty(...) on PHP < 8.4; deploying serialized service containers or cached metadata produced on a PHP 8.4 build to a PHP 8.1-8.3 runtime; custom code that copied PropertyAccessorFactory's logic without the version branch.","commonSituations":"Mixed-version deploy pipelines (build on latest PHP, run on older); downgrading a server's PHP without clearing var/cache; custom property-accessor wiring in bundles.","solutions":["Do not instantiate RawValuePropertyAccessor yourself — use PropertyAccessorFactory::createPropertyAccessor(), which falls back to ObjectCastPropertyAccessor below PHP 8.4.","Upgrade the runtime to PHP 8.4+ if your stack genuinely requires raw-value writes.","When downgrading PHP, clear cached containers/metadata (var/cache/*, doctrine cache) so no 8.4-built services are unserialized on the older runtime."],"exampleFix":"// before\n$accessor = RawValuePropertyAccessor::fromReflectionProperty($refl); // on PHP 8.3 -> LogicException\n\n// after\nuse Doctrine\\ORM\\Mapping\\PropertyAccessors\\PropertyAccessorFactory;\n$accessor = PropertyAccessorFactory::createPropertyAccessor($class, $property); // picks the right accessor per PHP version","handlingStrategy":"validation","validationCode":"if (PHP_VERSION_ID < 80400) {\n    // do not construct RawValuePropertyAccessor on this runtime\n    $accessor = PropertyAccessorFactory::createPropertyAccessor($class, $prop);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never instantiate RawValuePropertyAccessor directly; use PropertyAccessorFactory.","Keep build and runtime PHP versions aligned in the deploy pipeline.","Clear cached containers/metadata after changing the PHP version."],"tags":["doctrine-orm","property-accessor","php-84","runtime-version"],"backgroundTag":"php-version-requirement","analyzedSha":"d9b9ff73016bf598ae07515f97289ce8074e97a5","analyzedAt":"2026-08-21T06:13:15.863Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}