Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d2af4bf

Browse files
committed
QueryResultTypeWalker: precise type inferring
1 parent dd71401 commit d2af4bf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+2402
-428
lines changed

‎README.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,12 @@ $query->getOneOrNullResult(Query::HYDRATE_OBJECT); // User
152152

153153
This is due to the design of the `Query` class preventing from determining the hydration mode used by these functions unless it is specified explicitly during the call.
154154

155+
### Expression types inferring
156+
157+
Whether `MAX(e.id)` is fetched as `string` or `int` highly [depends on drivers, their setup and PHP version](https://github.com/janedbal/php-database-drivers-fetch-test).
158+
This extension copies the logic from linked analysis, autodetects your setup and provides accurate results for `pdo_mysql`, `mysqli`, `pdo_sqlite`, `sqlite3`, `pdo_pgsql` and `pgsql`.
159+
Any other driver will result in union with stringified version, e.g. `numeric-string|int`.
160+
155161
### Problematic approaches
156162

157163
Not every QueryBuilder can be statically analysed, here are few advices to maximize type inferring:

‎phpstan.neon‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,11 @@ parameters:
4949
- '#^Cannot call method getWrappedResourceHandle\(\) on class\-string\|object\.$#'
5050
path: tests/Platform/QueryResultTypeWalkerFetchTypeMatrixTest.php
5151
reportUnmatched: false
52+
-
53+
message: '#^Call to function method_exists\(\) with Doctrine\\DBAL\\Connection and ''getNativeConnection'' will always evaluate to true\.$#' # needed for older DBAL versions
54+
path: src/Type/Doctrine/Query/QueryResultTypeWalker.php
55+
-
56+
messages: # needed for older DBAL versions (fails only on PHP 7.3)
57+
- '#^Class Doctrine\\DBAL\\Driver\\PgSQL\\Driver not found\.$#'
58+
- '#^Class Doctrine\\DBAL\\Driver\\SQLite3\\Driver not found\.$#'
59+
path: src/Type/Doctrine/Query/QueryResultTypeWalker.php

‎src/Type/Doctrine/CreateQueryDynamicReturnTypeExtension.php‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Doctrine\Persistence\Mapping\MappingException;
1313
use PhpParser\Node\Expr\MethodCall;
1414
use PHPStan\Analyser\Scope;
15+
use PHPStan\Php\PhpVersion;
1516
use PHPStan\Reflection\MethodReflection;
1617
use PHPStan\Type\Constant\ConstantStringType;
1718
use PHPStan\Type\Doctrine\Query\QueryResultTypeBuilder;
@@ -37,10 +38,14 @@ final class CreateQueryDynamicReturnTypeExtension implements DynamicMethodReturn
3738
/** @var DescriptorRegistry */
3839
private $descriptorRegistry;
3940

40-
public function __construct(ObjectMetadataResolver $objectMetadataResolver, DescriptorRegistry $descriptorRegistry)
41+
/** @var PhpVersion */
42+
private $phpVersion;
43+
44+
public function __construct(ObjectMetadataResolver $objectMetadataResolver, DescriptorRegistry $descriptorRegistry, PhpVersion $phpVersion)
4145
{
4246
$this->objectMetadataResolver = $objectMetadataResolver;
4347
$this->descriptorRegistry = $descriptorRegistry;
48+
$this->phpVersion = $phpVersion;
4449
}
4550

4651
public function getClass(): string
@@ -87,7 +92,7 @@ public function getTypeFromMethodCall(
8792

8893
try {
8994
$query = $em->createQuery($queryString);
90-
QueryResultTypeWalker::walk($query, $typeBuilder, $this->descriptorRegistry);
95+
QueryResultTypeWalker::walk($query, $typeBuilder, $this->descriptorRegistry, $this->phpVersion);
9196
} catch (ORMException | DBALException | NewDBALException | CommonException | MappingException | \Doctrine\ORM\Exception\ORMException $e) {
9297
return new QueryType($queryString, null, null);
9398
} catch (AssertionError $e) {

‎src/Type/Doctrine/DefaultDescriptorRegistry.php‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,15 @@ public function get(string $type): DoctrineTypeDescriptor
3636
return $this->descriptors[$typeClass];
3737
}
3838

39+
/**
40+
* @throws DescriptorNotRegisteredException
41+
*/
42+
public function getByClassName(string $className): DoctrineTypeDescriptor
43+
{
44+
if (!isset($this->descriptors[$className])) {
45+
throw new DescriptorNotRegisteredException();
46+
}
47+
return $this->descriptors[$className];
48+
}
49+
3950
}

‎src/Type/Doctrine/Descriptors/ArrayType.php‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Type\Doctrine\Descriptors;
44

5+
use Doctrine\DBAL\Driver;
56
use PHPStan\Type\MixedType;
67
use PHPStan\Type\StringType;
78
use PHPStan\Type\Type;
@@ -24,7 +25,7 @@ public function getWritableToDatabaseType(): Type
2425
return new \PHPStan\Type\ArrayType(new MixedType(), new MixedType());
2526
}
2627

27-
public function getDatabaseInternalType(): Type
28+
public function getDatabaseInternalType(Driver$driver): Type
2829
{
2930
return new StringType();
3031
}

‎src/Type/Doctrine/Descriptors/AsciiStringType.php‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Type\Doctrine\Descriptors;
44

5+
use Doctrine\DBAL\Driver;
56
use PHPStan\Type\StringType;
67
use PHPStan\Type\Type;
78

@@ -23,7 +24,7 @@ public function getWritableToDatabaseType(): Type
2324
return new StringType();
2425
}
2526

26-
public function getDatabaseInternalType(): Type
27+
public function getDatabaseInternalType(Driver$driver): Type
2728
{
2829
return new StringType();
2930
}

‎src/Type/Doctrine/Descriptors/BigIntType.php‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace PHPStan\Type\Doctrine\Descriptors;
44

55
use Composer\InstalledVersions;
6+
use Doctrine\DBAL\Driver;
67
use PHPStan\Type\Accessory\AccessoryNumericStringType;
78
use PHPStan\Type\IntegerType;
89
use PHPStan\Type\StringType;
@@ -30,10 +31,10 @@ public function getWritableToPropertyType(): Type
3031

3132
public function getWritableToDatabaseType(): Type
3233
{
33-
return TypeCombinator::union(new StringType(), newIntegerType());
34+
return TypeCombinator::union(new StringType());
3435
}
3536

36-
public function getDatabaseInternalType(): Type
37+
public function getDatabaseInternalType(Driver$driver): Type
3738
{
3839
return new IntegerType();
3940
}

‎src/Type/Doctrine/Descriptors/BinaryType.php‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Type\Doctrine\Descriptors;
44

5+
use Doctrine\DBAL\Driver;
56
use PHPStan\Type\MixedType;
67
use PHPStan\Type\ResourceType;
78
use PHPStan\Type\StringType;
@@ -25,7 +26,7 @@ public function getWritableToDatabaseType(): Type
2526
return new MixedType();
2627
}
2728

28-
public function getDatabaseInternalType(): Type
29+
public function getDatabaseInternalType(Driver$driver): Type
2930
{
3031
return new StringType();
3132
}

‎src/Type/Doctrine/Descriptors/BlobType.php‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Type\Doctrine\Descriptors;
44

5+
use Doctrine\DBAL\Driver;
56
use PHPStan\Type\MixedType;
67
use PHPStan\Type\ResourceType;
78
use PHPStan\Type\Type;
@@ -24,7 +25,7 @@ public function getWritableToDatabaseType(): Type
2425
return new MixedType();
2526
}
2627

27-
public function getDatabaseInternalType(): Type
28+
public function getDatabaseInternalType(Driver$driver): Type
2829
{
2930
return new MixedType();
3031
}

‎src/Type/Doctrine/Descriptors/BooleanType.php‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace PHPStan\Type\Doctrine\Descriptors;
44

5+
use Doctrine\DBAL\Driver;
6+
use Doctrine\DBAL\Driver\PDO\PgSQL\Driver as PdoPgSQLDriver;
7+
use Doctrine\DBAL\Driver\PgSQL\Driver as PgSQLDriver;
58
use PHPStan\Type\Constant\ConstantIntegerType;
69
use PHPStan\Type\Type;
710
use PHPStan\Type\TypeCombinator;
@@ -24,12 +27,15 @@ public function getWritableToDatabaseType(): Type
2427
return new \PHPStan\Type\BooleanType();
2528
}
2629

27-
public function getDatabaseInternalType(): Type
30+
public function getDatabaseInternalType(Driver$driver): Type
2831
{
32+
if ($driver instanceof PgSQLDriver || $driver instanceof PdoPgSQLDriver) {
33+
return new \PHPStan\Type\BooleanType();
34+
}
35+
2936
return TypeCombinator::union(
3037
new ConstantIntegerType(0),
31-
new ConstantIntegerType(1),
32-
new \PHPStan\Type\BooleanType()
38+
new ConstantIntegerType(1)
3339
);
3440
}
3541

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /