有谁知道从 PHP 8.0 到 8.1 旧的 Doctrine 注释发生了什么变化?我有一个带有 Doctrine 注释的遗留代码,需要暂时迁移到 PHP 8.1。整个事情现在在 PHP 8.0 下运行。
在 PHP 8.1 下出现以下错误:
Doctrine\Common\Annotations\DocLexer::T_CLOSE_PARENTHESIS,
got 'CLASS' at position 25 in class @Doctrine\ORM\Mapping\Entity.
词法分析器/解析器不再正确解释以下注释
/**
* @Annotation
* @Target("CLASS")
*/
正如我所说,它在 8.0 下工作 - 代码/库中没有任何更改。我的猜测是,在 PHP 8.1 下,要么注释的解释不同(双引号?),要么比较操作(==)发生了变化。我认为双引号不再被正确识别。 这是一个快速、临时的解决方案。当前 Doctrine 版本的完整代码转换正在进行中,但由于项目的复杂性,需要一些时间。
完整的错误堆栈:
{
"file": "\/html\/frontend\/www\/backend\/vendor\/doctrine\/annotations\/lib\/Doctrine\/Common\/Annotations\/DocParser.php",
"line": 445,
"function": "syntaxError",
"class": "Doctrine\\Common\\Annotations\\AnnotationException",
"type": "::",
"args": [
"Expected Doctrine\\Common\\Annotations\\DocLexer::T_CLOSE_PARENTHESIS, got \u0027CLASS\u0027 at position 25 in class @Doctrine\\ORM\\Mapping\\Entity."
]
},
{
"file": "\/html\/frontend\/www\/backend\/vendor\/doctrine\/annotations\/lib\/Doctrine\/Common\/Annotations\/DocParser.php",
"line": 399,
"function": "syntaxError",
"class": "Doctrine\\Common\\Annotations\\DocParser",
"type": "-\u003E",
"args": [
"Doctrine\\Common\\Annotations\\DocLexer::T_CLOSE_PARENTHESIS"
]
},
{
"file": "\/html\/frontend\/www\/backend\/vendor\/doctrine\/annotations\/lib\/Doctrine\/Common\/Annotations\/DocParser.php",
"line": 863,
"function": "match",
"class": "Doctrine\\Common\\Annotations\\DocParser",
"type": "-\u003E",
"args": [
103
]
},
{
"file": "\/html\/frontend\/www\/backend\/vendor\/doctrine\/annotations\/lib\/Doctrine\/Common\/Annotations\/DocParser.php",
"line": 770,
"function": "MethodCall",
"class": "Doctrine\\Common\\Annotations\\DocParser",
"type": "-\u003E",
"args": []
},
{
"file": "\/html\/frontend\/www\/backend\/vendor\/doctrine\/annotations\/lib\/Doctrine\/Common\/Annotations\/DocParser.php",
"line": 654,
"function": "Annotation",
"class": "Doctrine\\Common\\Annotations\\DocParser",
"type": "-\u003E",
"args": []
},
{
"file": "\/html\/frontend\/www\/backend\/vendor\/doctrine\/annotations\/lib\/Doctrine\/Common\/Annotations\/DocParser.php",
"line": 359,
"function": "Annotations",
"class": "Doctrine\\Common\\Annotations\\DocParser",
"type": "-\u003E",
"args": []
},
{
"file": "\/html\/frontend\/www\/backend\/vendor\/doctrine\/annotations\/lib\/Doctrine\/Common\/Annotations\/DocParser.php",
"line": 515,
"function": "parse",
"class": "Doctrine\\Common\\Annotations\\DocParser",
"type": "-\u003E",
"args": [
"\/**\r\n * @Annotation\r\n * @Target(\u0022CLASS\u0022)\r\n *\/",
"class @Doctrine\\ORM\\Mapping\\Entity"
]
},
{
"file": "\/html\/frontend\/www\/backend\/vendor\/doctrine\/annotations\/lib\/Doctrine\/Common\/Annotations\/DocParser.php",
"line": 744,
"function": "collectAnnotationMetadata",
"class": "Doctrine\\Common\\Annotations\\DocParser",
"type": "-\u003E",
"args": [
"Doctrine\\ORM\\Mapping\\Entity"
]
},
{
"file": "\/html\/frontend\/www\/backend\/vendor\/doctrine\/annotations\/lib\/Doctrine\/Common\/Annotations\/DocParser.php",
"line": 654,
"function": "Annotation",
"class": "Doctrine\\Common\\Annotations\\DocParser",
"type": "-\u003E",
"args": []
},
{
"file": "\/html\/frontend\/www\/backend\/vendor\/doctrine\/annotations\/lib\/Doctrine\/Common\/Annotations\/DocParser.php",
"line": 359,
"function": "Annotations",
"class": "Doctrine\\Common\\Annotations\\DocParser",
"type": "-\u003E",
"args": []
},
{
"file": "\/html\/frontend\/www\/backend\/vendor\/doctrine\/annotations\/lib\/Doctrine\/Common\/Annotations\/AnnotationReader.php",
"line": 221,
"function": "parse",
"class": "Doctrine\\Common\\Annotations\\DocParser",
"type": "-\u003E",
"args": [
"\/**\n * @ORM\\Entity\n * @ORM\\Table(name=\u0022appointment\u0022)\n * @PIM\\Config(label=\u0022Termine\u0022, labelProperty=\u0022title\u0022, sortBy=\u0022bookedDate\u0022, tabs=\u0022{\u0027contact\u0027: \u0027Kundendaten\u0027}\u0022, sort=10)\n *\/",
"class Custom\\Entity\\Appointment\\Appointment"
]
},
{
"file": "\/html\/frontend\/www\/backend\/lib\/contentfly\/Classes\/Api.php",
"line": 1414,
"function": "getClassAnnotations",
"class": "Doctrine\\Common\\Annotations\\AnnotationReader",
"type": "-\u003E",
"args": [
{
"name": "Custom\\Entity\\Appointment\\Appointment"
}
]
}
这可能不是一个有效的答案,但是您是否尝试过以下语法:
/**
* @Annotation
* @Target({"CLASS"})
*/
对于处理遗留代码,我强烈建议使用 Rector 将代码更新到 PHP 8.1 标准。
安装校长:
command composer require --dev 'rector/rector'
首次启动Rector生成默认配置文件 (`rector.php`):
command php 'vendor/bin/rector' 'process' --dry-run
Symfony 项目的 Rector 配置示例(在
rector.php
中)是:
<?php
declare(strict_types=1);
use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
use Rector\Config\RectorConfig;
use Rector\Doctrine\Set\DoctrineSetList;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
use Rector\Symfony\Bridge\Symfony\Routing\SymfonyRoutesProvider;
use Rector\Symfony\CodeQuality\Rector\ClassMethod\ActionSuffixRemoverRector;
use Rector\Symfony\Contract\Bridge\Symfony\Routing\SymfonyRoutesProviderInterface;
use Rector\Symfony\Set\SymfonySetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->paths([
__DIR__.'/config',
__DIR__.'/public',
__DIR__.'/src',
__DIR__.'/tests',
]);
// register a single rule
$rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);
// Provide Symfony XML Service List.
$rectorConfig->symfonyContainerXml(__DIR__.'/var/cache/dev/App_KernelDevDebugContainer.xml');
// define sets of rules
$rectorConfig->sets([
SetList::DEAD_CODE,
LevelSetList::UP_TO_PHP_81,
DoctrineSetList::DOCTRINE_CODE_QUALITY,
SymfonySetList::SYMFONY_64,
SymfonySetList::SYMFONY_CODE_QUALITY,
SymfonySetList::SYMFONY_CONSTRUCTOR_INJECTION,
]);
// Provide Symfony PHP container.
$rectorConfig->symfonyContainerPhp(__DIR__.'/tests/RectorSymfonyContainer.php');
// Add Symfony Route annotation config.
$rectorConfig->singleton(SymfonyRoutesProvider::class);
$rectorConfig->alias(SymfonyRoutesProvider::class, SymfonyRoutesProviderInterface::class);
// skip ActionSuffixRemoverRector for SonataAdmin Controler.
$rectorConfig->skip([
ActionSuffixRemoverRector::class => [
__DIR__.'/src/*/Controller/Admin/*Controller.php',
],
]);
};
根据您的 PHP 和 Symfony 版本调整此配置(或者如果您的项目不使用 Symfony,则删除对 Symfony 的引用),并查看 Rector 提出的更改:
php 'vendor/bin/rector' 'process' --dry-run