이 확장자는 다음과 같은 기능을 제공합니다.
findBy* , findOneBy* 및 countBy* 메소드를 인식합니다.findBy , findBy* , findOneBy , findOneBy* , count 및 countBy* 메소드 호출의 엔터티 필드를 확인합니다.EntityRepository<MyEntity> 올바르게 해석합니다.DoctrineORMEntityManager::getRepository() 대한 올바른 수익을 제공합니다.Foo::class 엔티티 클래스 이름이 첫 번째 인수로 제공 될 때 DoctrineORMEntityManager::find , getReference 및 getPartialReference 에 대한 올바른 반환 유형을 제공합니다.DoctrineCommonCollectionsCollection 에 누락 된 matching 방법을 추가합니다. parameters.doctrine.allCollectionsSelectable 은 false 로 꺼집니다.allowNullablePropertyForRequiredField: true 설정으로 편안 할 수 있습니다.DoctrineORMQuery::getResult , getOneOrNullResult , getSingleResult , HYDRATE_OBJECT 모드에서 toIterable 하고 execute 대한 반환 유형을 제공합니다 (아래 참조). 이 확장을 사용하려면 작곡가에 필요합니다.
composer require --dev phpstan/phpstan-doctrinePhpstan/Extension-Installer도 설치하면 모두 설정됩니다!
phpstan/extension-installer 사용하지 않으려면 프로젝트의 Phpstan 구성에 Extension.neon을 포함시킵니다.
includes :
- vendor/phpstan/phpstan-doctrine/extension.neon DQL/QueryBuilder 유효성 검사에 관심이 있으시면 rules.neon 도 포함하십시오 ( objectManagerLoader 도 제공해야합니다. 아래 참조).
includes :
- vendor/phpstan/phpstan-doctrine/rules.neon 리포지토리에 공통 기본 클래스가있는 경우 Phpstan에서 구성 할 수 있습니다 phpstan.neon 및 Phpstan은 다음과 같은 추가 메소드를 볼 수 있습니다.
parameters :
doctrine :
ormRepositoryClass : MyAppDoctrineBetterEntityRepository
odmRepositoryClass : MyAppDoctrineBetterDocumentRepository자신의 애플리케이션에서 객체 관리자를 제공하여보다 고급 분석을 선택할 수 있습니다. 이렇게하면 DQL 유효성 검사가 가능합니다.
parameters :
doctrine :
objectManagerLoader : tests/object-manager.phpSymfony 4의 예 :
// tests/object-manager.php
use App Kernel ;
require __DIR__ . ' /../config/bootstrap.php ' ;
$ kernel = new Kernel ( $ _SERVER [ ' APP_ENV ' ], ( bool ) $ _SERVER [ ' APP_DEBUG ' ]);
$ kernel -> boot ();
return $ kernel -> getContainer ()-> get ( ' doctrine ' )-> getManager ();Symfony 5의 예 :
// tests/object-manager.php
use App Kernel ;
use Symfony Component Dotenv Dotenv ;
require __DIR__ . ' /../vendor/autoload.php ' ;
( new Dotenv ())-> bootEnv ( __DIR__ . ' /../.env ' );
$ kernel = new Kernel ( $ _SERVER [ ' APP_ENV ' ], ( bool ) $ _SERVER [ ' APP_DEBUG ' ]);
$ kernel -> boot ();
return $ kernel -> getContainer ()-> get ( ' doctrine ' )-> getManager (); 이 확장자는 objectManagerLoader 제공 될 때 DQL 쿼리의 결과 유형을 유추 할 수 있습니다.
예 :
$ query = $ entityManager -> createQuery ( ' SELECT u FROM AcmeUser u ' );
$ query -> getResult (); // array<AcmeUser>
$ query = $ entityManager -> createQuery ( ' SELECT u.id, u.email, u.name FROM AcmeUser u ' );
$ query -> getResult (); // array<array{id: int, email: string, name: string|null}>
$ query = $ entityManager -> createQuery ( '
SELECT u.id, u.email, COALESCE(u.name, "Anonymous") AS name
FROM AcmeUser u
' );
$ query -> getSingleResult (Query:: HYDRATE_OBJECT ); // array{id: int, email: string, name: string}>
$ query = $ entityManager -> createQueryBuilder ()
-> select ( ' u ' )
-> from (User::class, ' u ' )
-> getQuery ();
$ query -> getResult (); // array<AcmeUser>쿼리는 정적으로 분석되며 실행중인 데이터베이스 서버가 필요하지 않습니다. 이것은 교리 DQL 파서 및 엔티티 메타 데이터를 사용합니다.
GROUP BY , INDEX BY , DISTINCT , ArtIRMetic Expressions, Function, NEW 등 JOIN 모든 풍미를 포함하여 대부분의 DQL 기능이 지원됩니다. 하위 쿼리는 아직 지원되지 않습니다 (추론 된 유형은 mixed ).
예를 들어 SUM(e.column) float , numeric-string 또는 int 로 가져 오는지 여부는 드라이버, 설정 및 PHP 버전에 따라 크게 달라집니다. 이 Extension은 설정을 자동화하고 pdo_mysql , mysqli , pdo_sqlite , sqlite3 , pdo_pgsql 및 pgsql 에 대해 매우 정확한 결과를 제공합니다.
getResult 메소드는 인수없이 호출되거나 Query::HYDRATE_OBJECT 로 설정된 HydrateMode 인수로 지원됩니다.
$ query = $ entityManager -> createQuery ( ' SELECT u FROM AcmeUser u ' );
$ query -> getResult (); // array<User>
$ query -> getResult (Query:: HYDRATE_OBJECT ); // array<User> 방법은 Query::HYDRATE_OBJECT :: hydrate_object로 명시 적으로 설정 될 때 getOneOrNullResult , getSingleResult , toIterable 및 execute 지원됩니다.
$ query = $ entityManager -> createQuery ( ' SELECT u FROM AcmeUser u ' );
$ query -> getOneOrNullResult (); // mixed
$ query -> getOneOrNullResult (Query:: HYDRATE_OBJECT ); // User 이는 Query 클래스의 설계로 인해 통화 중에 명시 적으로 지정되지 않는 한 이러한 기능에서 사용하는 수화 모드를 결정하지 못하게합니다.
모든 querybuilder를 정적으로 분석 할 수있는 것은 아니며, 유형 추론을 극대화하기위한 몇 가지 조언은 다음과 같습니다.
select / join / from / set )다음과 같이 추론 할 수없는 장소를보고 할 수 있습니다.
parameters :
doctrine :
reportDynamicQueryBuilders : true 응용 프로그램에서 사용자 정의 교리 유형을 사용하는 경우 자신의 유형 설명자를 작성하여 제대로 분석 할 수 있습니다. 유형 디스크립터는 인터페이스 PHPStanTypeDoctrineDescriptorsDoctrineTypeDescriptor 구현합니다.
<?php
public function getType(): string ;
public function getWritableToPropertyType(): Type ;
public function getWritableToDatabaseType(): Type ;getType() 메소드는 사용자 정의 유형의 클래스 이름을 반환합니다.getWritableToPropertyType() 메소드는 사용자 정의 유형이 엔티티의 속성 필드에 기록하는 phpstan 유형을 반환합니다. 기본적으로 사용자 정의 유형의 convertToPHPValue() 메소드의 리턴 유형입니다.getWritableToDatabaseType() 메소드는 엔티티의 속성 필드에서 쓸 수있는 phpstan 유형을 사용자 정의 유형으로 반환합니다. 다시, 기본적으로 사용자 정의 유형의 convertToDatabaseValue() 의 첫 번째 인수에 대한 허용 유형입니다. 일반적으로, 적어도 대부분의 교리의 기본 유형의 경우,이 마지막 두 가지 방법은 같은 유형을 반환하지만 항상 그런 것은 아닙니다. 한 가지 예는 datetime 유형으로, DateTimeInterface 속성 필드로 설정할 수 있지만 데이터베이스에서로드 된 경우 항상 DateTime 유형을 포함합니다.
유형 설명자는 필요에 따라 디스크립터 유형에서 투명하게 추가/제거되므로 무효 유형을 처리 할 필요가 없습니다. 따라서 사용자 정의 유형이 null 허용하더라도 디스크립터 메소드에서 사용자 정의 유형 및 NullType 의 UNIN 유형을 반환 할 필요가 없습니다.
사용자 정의 유형의 convertToPHPValue() 및 convertToDatabaseValue() 메소드에 적절한 유형이있는 경우 자신의 디스크립터를 작성할 필요가 없습니다. PHPStanTypeDoctrineDescriptorsReflectionDescriptor 유형을 분석하고 나머지를 수행 할 수 있습니다.
귀하의 유형의 부모가 교리의 비 임금 중 하나 인 경우, ReflectionDescriptor 표현 해상도 (예 : AVG(t.cost) )를 위해 설명자를 재사용합니다. 예를 들어, DoctrineDBALTypesDecimalType 확장하면 sqlite가 그것을 float|int , 다른 드라이버로 numeric-string 로 가져옵니다. DoctrineDBALTypesType 만 확장하는 경우 사용자 정의 설명자를 사용하고 선택적으로 DoctrineTypeDriverAwareDescriptor 으로 구현하여 드라이버 별 해상도를 제공해야합니다.
사용자 정의 유형 디스크립터를 작성할 때는 Phpstan에게 알리십시오. phpstan.neon 에 이와 같은 것을 추가하십시오.
services :
-
class : MyCustomTypeDescriptor
tags : [ phpstan.doctrine.typeDescriptor ]
# in case you are using the ReflectionDescriptor
-
factory : PHPStanTypeDoctrineDescriptorsReflectionDescriptor ( ' MyAppMyCustomTypeName ' )
tags : [ phpstan.doctrine.typeDescriptor ]사용자 정의 유형에 대한 디스크립터를 잊지 않으려면 다음을 활성화 할 수 있습니다.
parameters :
doctrine :
reportUnknownTypes : true이로 인해 엔티티가 설명자없이 사용자 정의 유형을 사용하면 실패가 발생합니다.
#[Entity]
abstract class Uuid7Entity
{
#[Id]
#[Column(type: Uuid7Type:: NAME )] // reported when descriptor for such type is missing
private Uuid7 $ hsCode ; 교리의 TypedExpression 구현하는 모든 사용자 정의 DQL 기능은이 확장에 의해 이해되며 getReturnType() 메소드에 사용 된 유형으로 추론됩니다. 다른 모든 사용자 정의 DQL 기능은 mixed 것으로 추론됩니다. 기본 StringType 사용하여 문자열 결과를 캐스트하고 추론 할 수 없습니다 (ORM 문제 참조).
use Doctrine DBAL Types Type ;
use Doctrine DBAL Types Types ;
use Doctrine ORM Query AST TypedExpression ;
use Doctrine ORM Query AST Functions FunctionNode ;
use Doctrine ORM Query Parser ;
use Doctrine ORM Query SqlWalker ;
use Doctrine ORM Query TokenType ;
class Floor extends FunctionNode implements TypedExpression
{
private AST Node | string $ arithmeticExpression ;
public function getSql ( SqlWalker $ sqlWalker ): string
{
return ' FLOOR( ' . $ sqlWalker -> walkSimpleArithmeticExpression ( $ this -> arithmeticExpression ) . ' ) ' ;
}
public function parse ( Parser $ parser ): void
{
$ parser -> match (TokenType:: T_IDENTIFIER );
$ parser -> match (TokenType:: T_OPEN_PARENTHESIS );
$ this -> arithmeticExpression = $ parser -> SimpleArithmeticExpression ();
$ parser -> match (TokenType:: T_CLOSE_PARENTHESIS );
}
public function getReturnType (): Type
{
return Type:: getType (Types:: INTEGER );
}
} phpstan-doctrine의 스터브 파일에는 literal-string 표시된 많은 매개 변수가 있습니다. 이것은 코드로 작성된 문자열만이 이러한 매개 변수로 전달할 수있는 보안 중심 유형입니다.
이는 사용자 입력의 동적 문자열이 literal-string 대신 허용되지 않기 때문에 SQL 주입의 위험을 줄입니다.
이 유형이 사용되는 예는 DoctrineDbalConnection::executeQuery() 의 $sql 매개 변수입니다.
Phpstan-Doctrine 에서이 고급 유형을 활성화하려면이 구성 매개 변수를 사용하십시오.
parameters :
doctrine :
literalString : true