Diese Erweiterung enthält folgende Funktionen:
findBy* , findOneBy* und countBy* Methoden auf EntityRepository.findBy , findBy* , findOneBy , findOneBy* , count und countBy* Methodenaufrufe.EntityRepository<MyEntity> korrekt in PHPDOCs für weitere Typ -Inferenz von Methoden, die im Repository aufgerufen werden.DoctrineORMEntityManager::getRepository() .DoctrineORMEntityManager::find , getReference und getPartialReference wenn Foo::class -Entitätsklassenname als erstes Argument bereitgestellt wirdmatching für DoctrineCommonCollectionsCollection hinzu. Dies kann abgeschaltet werden, indem parameters.doctrine.allCollectionsSelectable false werden.allowNullablePropertyForRequiredField: true -Setting entspannt werden.DoctrineORMQuery::getResult , getOneOrNullResult , getSingleResult , toIterable und im HYDRATE_OBJECT -Modus execute (siehe unten). Um diese Erweiterung zu verwenden, benötigen Sie sie in Komponist:
composer require --dev phpstan/phpstan-doctrineWenn Sie auch Phpstan/Extension-Installer installieren, sind Sie alle festgelegt!
Wenn Sie phpstan/extension-installer nicht verwenden möchten, enthalten Sie die Erweiterung.neon in der Phpstan-Konfiguration Ihres Projekts:
includes :
- vendor/phpstan/phpstan-doctrine/extension.neon Wenn Sie an der DQL/QueryBuilder -Validierung interessiert sind, enthalten Sie auch rules.neon (Sie müssen auch den objectManagerLoader angeben, siehe unten):
includes :
- vendor/phpstan/phpstan-doctrine/rules.neon Wenn Ihre Repositories eine gemeinsame Basisklasse haben, können Sie sie in Ihrem phpstan.neon konfigurieren. Neon und Phpstan werden zusätzliche Methoden sehen, die Sie darin definieren:
parameters :
doctrine :
ormRepositoryClass : MyAppDoctrineBetterEntityRepository
odmRepositoryClass : MyAppDoctrineBetterDocumentRepositorySie können sich für eine fortgeschrittenere Analyse entscheiden, indem Sie dem Objektmanager aus Ihrer eigenen Anwendung bereitstellen. Dies ermöglicht die DQL -Validierung:
parameters :
doctrine :
objectManagerLoader : tests/object-manager.phpBeispiel für Symfony 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 ();Beispiel für 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 (); Diese Erweiterung kann den Ergebnistyp von DQL -Abfragen schließen, wenn ein objectManagerLoader bereitgestellt wird.
Beispiele:
$ 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>Abfragen werden statisch analysiert und benötigen keinen laufenden Datenbankserver. Dies nutzt den Doktrin -DQL -Parser und die Entitäten Metadaten.
Die meisten DQL -Merkmale werden unterstützt, einschließlich GROUP BY , INDEX BY , DISTINCT Geschmacksrichtungen von JOIN , arithmetischen Ausdrücken, Funktionen, Aggregationen, NEW usw. Unterabfragen werden noch nicht unterstützt (der Typ wird mixed ).
float SUM(e.column) numeric-string int Diese Erweiterung automatisiert Ihr Setup und liefert recht genaue Ergebnisse für pdo_mysql , mysqli , pdo_sqlite , sqlite3 , pdo_pgsql und pgsql .
Die getResult -Methode wird unterstützt, wenn sie ohne Argument aufgerufen wird, oder mit dem auf Query::HYDRATE_OBJECT :
$ query = $ entityManager -> createQuery ( ' SELECT u FROM AcmeUser u ' );
$ query -> getResult (); // array<User>
$ query -> getResult (Query:: HYDRATE_OBJECT ); // array<User> Die Methoden getOneOrNullResult , getSingleResult , toIterable und execute werden unterstützt, wenn das Argument des Hydratemode -Arguments explizit auf Query::HYDRATE_OBJECT :
$ query = $ entityManager -> createQuery ( ' SELECT u FROM AcmeUser u ' );
$ query -> getOneOrNullResult (); // mixed
$ query -> getOneOrNullResult (Query:: HYDRATE_OBJECT ); // User Dies ist auf das Design der Query zurückzuführen, die verhindert, dass der Hydratationsmodus, der von diesen Funktionen verwendet wird, nicht während des Anrufs explizit angegeben ist.
Nicht jeder QueryBuilder kann statisch analysiert werden. Hier sind nur wenige Ratschläge, um den Typ zu maximieren, das das Abschluss hat:
select / join / from / set ).Sie können die Berichterstattung über Orte ermöglichen, an denen das Ableiten nicht verfügbar ist durch:
parameters :
doctrine :
reportDynamicQueryBuilders : true Wenn Ihre Anwendung benutzerdefinierte Doktrinentypen verwendet, können Sie Ihre eigenen Typ -Deskriptoren schreiben, um sie ordnungsgemäß zu analysieren. Typ -Deskriptoren implementieren die Schnittstelle PHPStanTypeDoctrineDescriptorsDoctrineTypeDescriptor die so aussieht:
<?php
public function getType(): string ;
public function getWritableToPropertyType(): Type ;
public function getWritableToDatabaseType(): Type ;getType() gibt einfach den Klassennamen des benutzerdefinierten Typs zurück.getWritableToPropertyType() -Methode gibt den Phpstan -Typ zurück, den der benutzerdefinierte Typ in das Eigenschaftsfeld der Entität schreibt. Grundsätzlich ist es der Rückgabetyp der Methode convertToPHPValue() des benutzerdefinierten Typs.getWritableToDatabaseType() gibt den Phpstan -Typ zurück, der aus dem Eigenschaftsfeld der Entität in den benutzerdefinierten Typ geschrieben werden kann. Im Grunde ist es im Grunde genommen der zulässige Typ für das erste Argument des benutzerdefinierten convertToDatabaseValue() . Im Allgemeinen werden diese letzten beiden Methoden zumindest für die meisten nativen Typen der Doktrin denselben Typ zurückgeben, aber nicht immer der Fall. Ein Beispiel wäre der datetime -Typ, mit dem Sie ein beliebiges DateTimeInterface in das Eigenschaftsfeld festlegen können, aber immer den DateTime -Typ enthalten, wenn Sie aus der Datenbank geladen werden.
Typ -Deskriptoren müssen sich nicht mit nullbaren Typen befassen, da diese nach Bedarf transparent hinzugefügt/entfernt/entfernt werden. Daher müssen Sie den Gewerkschaftstyp Ihres benutzerdefinierten Typs und NullType nicht aus den Methoden des Deskriptors zurückgeben, auch wenn Ihr benutzerdefinierter Typ null zulässt.
Wenn die Methoden Ihres benutzerdefinierten Typs convertToPHPValue() und convertToDatabaseValue() ordnungsgemäße TypeHints enthalten, müssen Sie keinen eigenen Deskriptor dafür schreiben. Der PHPStanTypeDoctrineDescriptorsReflectionDescriptor kann die TypenHells analysieren und den Rest für Sie erledigen.
Wenn Eltern Ihres Typs einer der nicht abstrakten der Doktrin sind, wird ReflectionDescriptor seinen Deskriptor auch für die Expressionsauflösung (z. B. AVG(t.cost) ) wiederverwenden. Wenn Sie beispielsweise DoctrineDBALTypesDecimalType erweitern, wird wissen, dass SQLite das als float|int und andere Treiber als numeric-string abgerufen. Wenn Sie nur DoctrineDBALTypesType erweitern, sollten Sie den benutzerdefinierten Deskriptor verwenden und optional auch DoctrineTypeDriverAwareDescriptor implementieren, um eine fahrerspezifische Auflösung bereitzustellen.
Wenn Sie einen benutzerdefinierten Typ -Deskriptor schreiben, müssen Sie Phpstan darüber informieren. Fügen Sie so etwas in Ihren phpstan.neon hinzu:
services :
-
class : MyCustomTypeDescriptor
tags : [ phpstan.doctrine.typeDescriptor ]
# in case you are using the ReflectionDescriptor
-
factory : PHPStanTypeDoctrineDescriptorsReflectionDescriptor ( ' MyAppMyCustomTypeName ' )
tags : [ phpstan.doctrine.typeDescriptor ]Wenn Sie sicher sein möchten, dass Sie den Deskriptor für einen benutzerdefinierten Typ nie vergessen, können Sie aktivieren:
parameters :
doctrine :
reportUnknownTypes : trueDies führt zu Fehlern, wenn Ihr Entität einen benutzerdefinierten Typ ohne Deskriptor verwendet:
#[Entity]
abstract class Uuid7Entity
{
#[Id]
#[Column(type: Uuid7Type:: NAME )] // reported when descriptor for such type is missing
private Uuid7 $ hsCode ; Jede benutzerdefinierte DQL -Funktion, die TypedExpression von Doctrine implementiert, wird durch diese Erweiterung verstanden und wird mit dem Typ, der in seiner getReturnType() -Methode () verwendet wird, abgeleitet. Alle anderen benutzerdefinierten DQL -Funktionen werden als mixed abgeleitet. Bitte beachten Sie, dass Sie native StringType nicht verwenden können, um die String -Ergebnisse zu gießen (und zu schließen) (siehe ORM -Problem).
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 );
}
} Stub-Dateien in Phpstan-docTrin sind mit vielen Parametern mit literal-string ausgestattet. Dies ist ein sicherheitsorientierter Typ, mit dem nur die in Code geschriebenen buchstäblichen Zeichenfolgen in diese Parameter übergeben werden können.
Dies verringert das Risiko einer SQL-Injektion, da dynamische Zeichenfolgen der Benutzereingabe anstelle der literal-string nicht akzeptiert werden.
Ein Beispiel, bei dem dieser Typ verwendet wird, ist $sql -Parameter in DoctrineDbalConnection::executeQuery() .
Verwenden Sie diesen Konfigurationsparameter, um diesen erweiterten Typ in Phpstan-DocTrin zu aktivieren:
parameters :
doctrine :
literalString : true