我将 PHP8、symfony5 和doctrine2 与 phpstan 一起使用并收到以下错误:
Property App\Entity\User::$id is never written, only read.
Run Code Online (Sandbox Code Playgroud)
代码:
<?php
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* @ORM\Table(name="`user`")
* @ORM\Entity(repositoryClass=UserRepository::class)
* @UniqueEntity(fields={"email"}, message="There is already an account with this email")
*/
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
public const ROLE_USER = 'ROLE_USER';
public const ROLE_ADMIN = 'ROLE_ADMIN';
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=180, unique=true) …Run Code Online (Sandbox Code Playgroud) PHPStan 中如何处理这些场景:
Run Code Online (Sandbox Code Playgroud)// view.php <b><?=$foo?></b>
a.php并且b.phpRun Code Online (Sandbox Code Playgroud)// a.php $foo = 'bar'; // b.php require 'a.php'; echo $foo;
PHPStan 都会将此报告为Undefined variable: $foo
你如何处理这个问题?PHPStan 是否可以配置为以某种方式执行您的应用程序,以便它知道这些变量实际上是在运行时定义的?
我在一个Symfony项目上运行PHPStan,其中我在Doctrine实体中有以下关系:
/**
* @ORM\OneToMany(targetEntity="App\Entity\Course\Slide", mappedBy="chapter", cascade={"persist"}, orphanRemoval=true)
* @ORM\OrderBy({"listOrder" = "ASC"})
*
* @var ArrayCollection<Slide>
*/
private $slides;
Run Code Online (Sandbox Code Playgroud)
使用规则级别 6运行分析我收到以下有关该属性(及其 getter 返回类型)的消息:
App\Entity\Course\Chapter::$slides具有泛型类的属性Doctrine\Common\Collections\ArrayCollection未指定其类型:TKey, T
您可以通过checkGenericClassInNonGenericObjectType: false在您的phpstan.neon.
我的编辑尝试只会混淆 PHPStan,可能是因为我没有完全理解这里的泛型。但是仅仅因为我不明白而将消息静音将是愚蠢的。
我应该在 PHPDoc 中添加或更改什么?
为了实现对某些魔术_get()函数的检查,我正在尝试实现“类反射扩展”。该手册提到了如何编写扩展文件本身,以及如何通过service向 neon 文件添加一部分来安装它们。
我写了一个扩展,并像这样添加它:
services:
-
class: TestClass
tags:
- phpstan.broker.methodsClassReflectionExtension
Run Code Online (Sandbox Code Playgroud)
这会导致以下错误:
服务“0226”:未找到类 TestClass。
我尝试过的事情:
如果找不到文件,这些“添加”尝试中的一些实际上会发出警告:例如,如果我故意在其中之一中犯了一个拼写错误,比如说自动加载错误,它会警告我丢失文件。但前提是我没有定义service。
如果我定义了服务并在那里故意输入错误,它会返回上面的类未找到(而不是输入错误),所以我觉得它在任何参数之前检查扩展?
似乎需要将我的文件添加到不同的自动加载机制中。问题是,哪个以及如何?
我在用着
我确信这个问题已经被问过很多次了,但我似乎找不到一个好的/令人满意的答案,所以请直接告诉我。
使用 PHP 7.4+,我倾向于输入我能输入的所有内容。但我对学说实体属性有一些问题。
如果我正确输入所有内容,我通常会遇到很多像这样的错误。
初始化之前不得访问类型化属性 App\Entity\User::$createdAt
该类型错误的代码示例如下所示
/**
* @var DateTimeInterface
* @ORM\Column(type="datetime")
*/
protected DateTimeInterface $createdAt;
Run Code Online (Sandbox Code Playgroud)
因此,我曾经使属性可以为空,即使数据库字段不是。所以它看起来像这样。
/**
* @var DateTimeInterface|null
* @ORM\Column(type="datetime")
*/
protected ?DateTimeInterface $createdAt = null;
Run Code Online (Sandbox Code Playgroud)
但是,现在我有另一个问题。我决定在我的项目中实现静态代码分析器,现在我使用 PHPStan。所以现在,当我扫描代码时,我会收到类似的错误。
src/Entity/Trait/TimestampableEntityPropertiesTrait.php 行(在 App\Entity\Article 类的上下文中)
16 属性 App\Entity\Article::$createdAt 类型映射不匹配:属性可以包含 DateTimeInterface|null 但数据库需要 DateTimeInterface。
那么,处理这种情况的正确方法是什么?
任何建议将不胜感激。
编辑
我应该提到,有时,我不想/无法初始化构造函数中的属性,因为我还没有正确的值。
我正在 Symfony 6 应用程序中试验 PHP 枚举,我认为我找到了一个非常好的用例。一切正常,但 phpstan 一直抱怨我返回的类型。
------ -----------------------------------------------------------------------------------------------------------------------------------------------
Line src/Entity/User.php
------ -----------------------------------------------------------------------------------------------------------------------------------------------
93 Return type (array<App\Security\Roles>) of method App\Entity\User::getRoles() should be compatible with return type (array<string>) of method
Symfony\Component\Security\Core\User\UserInterface::getRoles()
------ -----------------------------------------------------------------------------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
我的枚举看起来像这样:
namespace App\Security;
enum Roles: string
{
case Admin = 'ROLE_ADMIN';
case User = 'ROLE_USER';
}
Run Code Online (Sandbox Code Playgroud)
在我User实现的实体中Symfony\Component\Security\Core\User\UserInterface,我有这个:
/**
* @see UserInterface
* @return array<Roles>
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = …Run Code Online (Sandbox Code Playgroud) 例如,如果我有一个这样的课程:
class Foo
{
/**
* @var array<string, array{name: string, age: int}>
*/
private array $things;
/**
* @return array
*/
public function getThings(): array
{
return $this->things;
}
}
Run Code Online (Sandbox Code Playgroud)
然后 phpstan 会给我一些类似于Method Foo::getThings() return type has no value type specified in iterable type array.
当然,我可以通过将数组形状定义添加到 来解决这个问题@return,但考虑到我已经在属性上定义了这个,有没有办法避免我在这里缺少的重复?
在我的代码中,我调用一个方法,其返回值的类型如下:
/**
* @return array<int, array<string,mixed>>
*/
public function fetchAllAssociative(): array;
Run Code Online (Sandbox Code Playgroud)
子类型array<string, mixed>以通用方式描述数据库记录。我确切地知道这个数据库记录是什么样的,所以我想更具体地记录该方法:
/**
* @return array<int, array{id: int, firstName: string, lastName: string}>
*/
public function getAllUsers(): array
{
return $this->userRepository->fetchAllAssociative();
}
Run Code Online (Sandbox Code Playgroud)
然而,PHPStan 抱怨说我应该完全按照以下方式键入我的方法fetchAllAssociative:
Method UserRepository::getAllUsers() should return array<int, array{id: int, firstName: string, lastName: string}> but returns array<int, array<string, mixed>>.
有办法投吗?我的解决方法是引入一个新变量并使用@var标签,但我不太喜欢它(其他静态代码分析工具也不喜欢它)
/**
* @return array<int, array{id: int, firstName: string, lastName: string}>
*/
public function getAllUsers(): array
{
/**
* @var array<int, array{id: int, firstName: …Run Code Online (Sandbox Code Playgroud) 使用 phpstan/larastan 分析代码时如何处理 Laravel 中的范围?
我收到此错误:
Call to an undefined method Illuminate\Database\Eloquent\Builder::active().
Run Code Online (Sandbox Code Playgroud)
我需要以某种方式输入提示吗?
我试图避免@phpstan-ignore-next-line
值得一提的是,仅当我在作用域内使用作用域时才会出现上述错误。在其他情况下,成功LaraStan阻止PhpStan警告。
升级到 Laravel 10 后,我遇到了 Larastan 错误的困难时期。
下面的代码在 1 小时前还完全正常:
return $this->articleRepository->getDefaultArticles($organizationId)
->toBase()
->map(function (Article $article) {
return new Content(
$article->id,
$article->title,
$article->language,
);
})
->toArray();
Run Code Online (Sandbox Code Playgroud)
现在给我以下错误:
方法 Illuminate\Support\Collection<(int|string),Illuminate\Database\Eloquent\Model>::map() 的参数 #1 $callback 需要 callable(Illuminate\Database\Eloquent\Model, int|string): App\学院\内容,
关闭(应用程序\模型\文章):给出的应用程序\学院\内容
存储库方法有正确的提示:
/**
* @return Collection<Article>
*/
public function getDefaultArticles(OrganizationId $organizationId): Collection
{
/** @var Collection<Article> */
return Article::query()
->where('organization_id', $organizationId)
->get()
->keyBy('id')
->values();
}
Run Code Online (Sandbox Code Playgroud)
它给了我 115 个新错误,其中大多数与此类似,与map和等收集方法相关reduce。
快速解决方案是使用临时变量并添加类型提示:
/** @var Collection<Article> $articles */
$articles = $this->articleRepository
->getDefaultArticles($organizationId)
->toBase();
Run Code Online (Sandbox Code Playgroud)
但我不想执行 100 …