この拡張機能は次の機能を提供します。
findBy* 、 findOneBy* 、 countBy* Methodを認識します。findBy 、 findBy* 、 findOneBy 、 findOneBy* 、 countおよびcountBy*メソッド呼び出しでエンティティフィールドを検証します。EntityRepository<MyEntity>正しく解釈します。DoctrineORMEntityManager::getRepository()に正しい返品を提供します。DoctrineORMEntityManager::find 、 getReference and getPartialReferenceの正しいリターンタイプを提供しますFoo::classDoctrineCommonCollectionsCollectionに欠落しているmatching方法を追加します。これは、 parameters.doctrine.allCollectionsSelectable falseに設定することでオフにできます。allowNullablePropertyForRequiredField: true設定でリラックスできます。DoctrineORMQuery::getResult 、 getOneOrNullResult 、 getSingleResult 、 toIterable 、およびHYDRATE_OBJECTモードでexecuteなリターンタイプを提供します(以下を参照)。 この拡張機能を使用するには、作曲家でそれを必要とします。
composer require --dev phpstan/phpstan-doctrinePHPSTAN/Extension-Installerもインストールする場合は、すべて設定されています。
phpstan/extension-installer使用したくない場合は、プロジェクトのphpstan configにextension.neonを含めます。
includes :
- vendor/phpstan/phpstan-doctrine/extension.neon DQL/QueryBuilderの検証に興味がある場合は、 rules.neonも含めます。Neon( objectManagerLoaderを提供する必要があります。以下を参照):
includes :
- vendor/phpstan/phpstan-doctrine/rules.neon リポジトリに共通のベースクラスがある場合、 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>クエリは静的に分析され、実行中のデータベースサーバーは必要ありません。これにより、Doctrine DQLパーサーとエンティティメタデータが利用されます。
GROUP BY 、 INDEX BY 、 DISTINCTのすべてのJOIN 、算術式、関数、集約、 NEWなどを含む、ほとんどのDQL機能がサポートされています。サブクエリはまだサポートされていません(推測されたタイプはmixedます)。
EG SUM(e.column)がfloat 、 numeric-string 、またはintがドライバー、セットアップ、PHPバージョンに大きく依存しているかどうかをフェッチします。この拡張機能はセットアップを自動検出し、 pdo_mysql 、 mysqli 、 pdo_sqlite 、 sqlite3 、 pdo_pgsql 、 pgsqlの非常に正確な結果を提供します。
getResultメソッドは、引数なしで呼び出されるとサポートされますQuery::HYDRATE_OBJECT
$ query = $ entityManager -> createQuery ( ' SELECT u FROM AcmeUser u ' );
$ query -> getResult (); // array<User>
$ query -> getResult (Query:: HYDRATE_OBJECT ); // array<User> HydrateMode引数が明示的にQuery::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()の最初の引数の許可されたタイプです。一般に、少なくとも教義のネイティブタイプのほとんどでは、これらの最後の2つの方法は同じタイプを返しますが、常にそうではありません。 1つの例は、 datetimeタイプです。これにより、 DateTimeInterfaceプロパティフィールドに設定できますが、データベースからロードされたときにDateTimeタイプが常に含まれます。
タイプの記述子は、必要に応じて記述子のタイプから透過的に追加/削除されるため、ヌル可能なタイプを処理する必要はありません。したがって、カスタムタイプがnull許可する場合でも、記述子のメソッドからカスタムタイプとNullTypeのユニオンタイプを返す必要はありません。
カスタムタイプのconvertToPHPValue()およびconvertToDatabaseValue()メソッドに適切なタイプヒントがある場合、独自の記述子を記述する必要はありません。 PHPStanTypeDoctrineDescriptorsReflectionDescriptorタイプヒントを分析し、残りを実行できます。
あなたのタイプの親が教義の非抽象的なものの1つである場合、 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 ;DoctrineのTypedExpressionを実装するカスタムDQL関数は、この拡張機能によって理解され、 getReturnType()メソッドで使用されるタイプで推測されます。他のすべてのカスタムDQL関数は、 mixedとして推測されます。ネイティブStringTypeを使用して文字列の結果をキャスト(推測する)ことはできないことに注意してください(ORM Issueを参照)。
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