如何告诉PHPStan$entry包含一个动态类型的对象(变量中的实体名)



我在9级的项目中运行PHPStan,现在我已经接近零错误了。不过,我找不到解决方案的一个问题是我项目的CRUD部分。

带有>50个需要权限、有关系等的复杂实体。当然,我无法多次编写CRUD部分,一遍又一遍地重复相同的逻辑和模板。相反,我有一个中央CrudController,实体的名称以及例如需要更新的特定条目的ID都是URL的一部分:

.../crud/[Entity]/[ID],例如.../crud/Article/123

控制器操作(Symfony此处=类方法(然后采用变量$entity中实体的名称,以加载ID在$ID中的特定条目。所以不是

$entry = new Article(...);

我必须加载正确的实体,如下所示:

$entry = new $entity(...);

我的CRUD中的所有东西都已经工作了。这里的问题是PHPStan不理解返回的对象的类型。我试过各种方法,比如

/** @var $entity $entry */

在变量$entry的声明之上,但无效。PHPStan只是抛出类似的错误

PHPDoc tag @var contains unknown class ...PHPDoc tag @var has invalid value...

以下是这个问题在操场上的一个非常基本的版本:https://phpstan.org/r/d9cb71bc-f2c5-4387-a3d6-841656824d41

如果没有像@var这样的东西,$entry发生的任何其他事情都会引发错误,例如:

$id = $entry->getId();投掷Call to undefined method object::getId().

我在文档中读到过关于泛型/模板等的内容,但那并不成功。我无法更改实体或它们的PHPDoc注释。所以我想我必须依赖变量声明上方的@var。但我也不能添加所有可能的实体名称,比如:

/** @var Article|Blog|Statistic|... $entry */

那么,有没有一种干净的方法可以告诉PHPDoc对象类型是动态的,并且基于$entity?

phpstan/条令扩展将为您解决大部分这些问题。然而,PHPStan实际上并没有运行任何代码,因此它不可能在运行时处理变量中存在未知动态类名的情况。你可以忽略:

// @phpstan-ignore-next-line
$id = $entry->getId();

或者,如果getId()是以这种方式使用的唯一方法,则可以为该方法创建一个接口:

interface IdInterface {
public function getId();
}

然后让你的所有实体实现:

class Article implements IdInterface {
public function getId() {
return $this->id;
}
// ...
}

然后你可以在界面上键入提示:

/** @var IdInterface $entry */
$entry = new $entity(...);
$id = $entry->getId();

最新更新