Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 18 additions & 111 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,118 +1,25 @@
# `phpstan-dba`: PHPStan based SQL static analysis and type inference for the database access layer
phpstan bug repro

`phpstan-dba` makes your phpstan static code analysis jobs aware of datatypes within your database.
With this information at hand we are able to detect type inconsistencies between your domain model and database-schema.
Additionally errors in code handling the results of sql queries can be detected.
- clone the repository
- checkout this PR
- composer install

This extension provides the following features, as long as you [stick to the rules](https://staabm.github.io/2022/07/23/phpstan-dba-inference-placeholder.html#the-golden-phpstan-dba-rules):
`vendor/bin/phpstan analyze src/SqlAst/ParserInference.php --debug`

* [result set type-inference](https://staabm.github.io/2022/06/19/phpstan-dba-type-inference.html)
* [detect errors in sql queries](https://staabm.github.io/2022/08/05/phpstan-dba-syntax-error-detection.html)
* [detect placeholder/bound value mismatches](https://staabm.github.io/2022/07/30/phpstan-dba-placeholder-validation.html)
* [query plan analysis](https://staabm.github.io/2022/08/16/phpstan-dba-query-plan-analysis.html) to detect performance issues
* builtin support for `doctrine/dbal`, `mysqli`, and `PDO`
* API to configure the same features for your custom sql based database access layer
* Opt-In analysis of write queries (since version 0.2.55+)
leads to

In case you are using Doctrine ORM, you might use `phpstan-dba` in tandem with [phpstan-doctrine](https://github.com/phpstan/phpstan-doctrine).

> [!NOTE]
> At the moment only MySQL/MariaDB and PGSQL databases are supported. Technically it's not a big problem to support other databases though.

## Talks

[phpstan-dba - check your sql queries like a boss](https://staabm.github.io/talks/phpstan-dba@phpugffm/)
May 2023, at PHP Usergroup in Frankfurt Main (Germany).

## DEMO

see the ['Files Changed' tab of the DEMO-PR](https://github.com/staabm/phpstan-dba/pull/61/files#diff-98a3c43049f6a0c859c0303037d9773534396533d7890bad187d465d390d634e) for a quick glance.

## 💌 Support phpstan-dba

[Consider supporting the project](https://github.com/sponsors/staabm), so we can make this tool even better even faster for everyone.

## Installation

**First**, use composer to install:

```shell
composer require --dev staabm/phpstan-dba
```

**Second**, create a `phpstan-dba-bootstrap.php` file, which allows to you to configure `phpstan-dba` (this optionally includes database connection details, to introspect the database; if you would rather not do this see [Record and Replay](https://github.com/staabm/phpstan-dba/blob/main/docs/record-and-replay.md):

```php
<?php // phpstan-dba-bootstrap.php

use staabm\PHPStanDba\DbSchema\SchemaHasherMysql;
use staabm\PHPStanDba\QueryReflection\RuntimeConfiguration;
use staabm\PHPStanDba\QueryReflection\MysqliQueryReflector;
use staabm\PHPStanDba\QueryReflection\QueryReflection;
use staabm\PHPStanDba\QueryReflection\ReplayAndRecordingQueryReflector;
use staabm\PHPStanDba\QueryReflection\ReplayQueryReflector;
use staabm\PHPStanDba\QueryReflection\ReflectionCache;

require_once __DIR__ . '/vendor/autoload.php';

$cacheFile = __DIR__.'/.phpstan-dba.cache';

$config = new RuntimeConfiguration();
// $config->debugMode(true);
// $config->stringifyTypes(true);
// $config->analyzeQueryPlans(true);
// $config->utilizeSqlAst(true);

// TODO: Put your database credentials here
$mysqli = new mysqli('hostname', 'username', 'password', 'database');

QueryReflection::setupReflector(
new ReplayAndRecordingQueryReflector(
ReflectionCache::create(
$cacheFile
),
// XXX alternatively you can use PdoMysqlQueryReflector instead
new MysqliQueryReflector($mysqli),
new SchemaHasherMysql($mysqli)

),
$config
);
```

> [!NOTE]
> [Configuration for PGSQL](https://github.com/staabm/phpstan-dba/blob/main/docs/pgsql.md) is pretty similar

**Third**, create or update your `phpstan.neon` file so [bootstrapFiles](https://phpstan.org/config-reference#bootstrap) includes `phpstan-dba-bootstrap.php`.

If you are **not** using [phpstan/extension-installer](https://github.com/phpstan/extension-installer), you will also need to include `dba.neon`.

Your `phpstan.neon` might look something like:

```neon
parameters:
level: 8
paths:
- src/
bootstrapFiles:
- phpstan-dba-bootstrap.php

includes:
- ./vendor/staabm/phpstan-dba/config/dba.neon
➜ phpstan-dba git:(staabm-patch-3) ✗ vendor/bin/phpstan analyze src/SqlAst/ParserInference.php --debug
Note: Using configuration file /Users/staabm/workspace/phpstan-dba/phpstan.neon.dist.
/Users/staabm/workspace/phpstan-dba/src/SqlAst/ParserInference.php
------ ---------------------------------------------
Line ParserInference.php
------ ---------------------------------------------
51 Cannot call method getCondition() on mixed.
🪪 method.nonObject
55 Cannot call method getLeft() on mixed.
🪪 method.nonObject
------ ---------------------------------------------
```

**Finally**, run `phpstan`, e.g.

```shell
./vendor/bin/phpstan analyse -c phpstan.neon
```

## Read more

- [Runtime configuration](https://github.com/staabm/phpstan-dba/blob/main/docs/configuration.md)
- [Record and Replay](https://github.com/staabm/phpstan-dba/blob/main/docs/record-and-replay.md)
- [Custom Query API Support](https://github.com/staabm/phpstan-dba/blob/main/docs/rules.md)
- [MySQL Support](https://github.com/staabm/phpstan-dba/blob/main/docs/mysql.md)
- [PGSQL Support](https://github.com/staabm/phpstan-dba/blob/main/docs/pgsql.md)
- [Reflector Overview](https://github.com/staabm/phpstan-dba/blob/main/docs/reflectors.md)
- [How to analyze a PHP 7.x codebase?](https://github.com/staabm/phpstan-dba/blob/main/docs/faq.md)
-> why does `$from` in `src/SqlAst/ParserInference.php` turn into `mixed`?
10 changes: 5 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@
"composer-runtime-api": "^2.0",
"composer/semver": "^3.2",
"doctrine/dbal": "3.*",
"phpstan/phpstan": "^1.9.4"
"phpstan/phpstan": "^2.0",
"sqlftw/sqlftw": "^0.1.16"
},
"require-dev": {
"ext-mysqli": "*",
"ext-pdo": "*",
"dibi/dibi": "^4.2",
"php-parallel-lint/php-parallel-lint": "^1.4",
"phpstan/extension-installer": "^1.4",
"phpstan/phpstan-deprecation-rules": "^1.1",
"phpstan/phpstan-phpunit": "^1.0",
"phpstan/phpstan-strict-rules": "^1.1",
"phpstan/phpstan-deprecation-rules": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^8.5|^9.5",
"symplify/easy-coding-standard": "^12.3",
"tomasvotruba/unused-public": "^1.0",
"vlucas/phpdotenv": "^5.4"
},
"conflict": {
Expand Down
28 changes: 0 additions & 28 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -1,36 +1,8 @@
includes:
- config/extensions.neon
- config/rules.neon
- phpstan-baseline.neon

parameters:
editorUrl: 'phpstorm://open?file=%%file%%&line=%%line%%'

level: max

paths:
- src/

bootstrapFiles:
- bootstrap.php

unused_public:
methods: true
properties: true
constants: true

reportUnmatchedIgnoredErrors: false

ignoreErrors:
-
message: '#^Method staabm\\PHPStanDba\\DbSchema\\SchemaHasherMysql\:\:hashDb\(\) should return string but returns float\|int\|string\.$#'
path: src/DbSchema/SchemaHasherMysql.php
-
message: '#^Property staabm\\PHPStanDba\\DbSchema\\SchemaHasherMysql\:\:\$hash \(string\|null\) does not accept float\|int\|string\.$#'
path: src/DbSchema/SchemaHasherMysql.php
-
message: '#^Instanceof between mysqli_result\<array\<string, int\|string\|null\>\> and mysqli_result will always evaluate to true\.$#'
path: src/DbSchema/SchemaHasherMysql.php
-
message: '#^Instanceof between mysqli_result<array<string, int<-2147483648, 2147483647>\|string\|null>> and mysqli_result will always evaluate to true\.$#'
path: src/DbSchema/SchemaHasherMysql.php
5 changes: 3 additions & 2 deletions src/DoctrineReflection/DoctrineResultObjectType.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Doctrine\DBAL\Result;
use PHPStan\ShouldNotHappenException;
use PHPStan\TrinaryLogic;
use PHPStan\Type\IsSuperTypeOfResult;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;

Expand Down Expand Up @@ -51,10 +52,10 @@ public function equals(Type $type): bool
return parent::equals($type);
}

public function isSuperTypeOf(Type $type): TrinaryLogic
public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
{
if ($type instanceof self) {
return TrinaryLogic::createFromBoolean(
return IsSuperTypeOfResult::createFromBoolean(
$type->rowType !== null
&& $this->rowType !== null
&& $type->rowType->equals($this->rowType)
Expand Down
5 changes: 3 additions & 2 deletions src/DoctrineReflection/DoctrineStatementObjectType.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Doctrine\DBAL\Statement;
use PHPStan\ShouldNotHappenException;
use PHPStan\TrinaryLogic;
use PHPStan\Type\IsSuperTypeOfResult;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;

Expand Down Expand Up @@ -51,10 +52,10 @@ public function equals(Type $type): bool
return parent::equals($type);
}

public function isSuperTypeOf(Type $type): TrinaryLogic
public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
{
if ($type instanceof self) {
return TrinaryLogic::createFromBoolean(
return IsSuperTypeOfResult::createFromBoolean(
$type->rowType !== null
&& $this->rowType !== null
&& $type->rowType->equals($this->rowType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private function reduceResultType(MethodReflection $methodReflection, Type $resu
if ('fetch' === $methodName) {
return TypeCombinator::addNull($resultType);
} elseif ('fetchAll' === $methodName) {
return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $resultType));
return TypeCombinator::intersect(new ArrayType(new IntegerType(), $resultType), new AccessoryArrayListType());
} elseif ('fetchPairs' === $methodName && $resultType instanceof ConstantArrayType && 2 === \count($resultType->getValueTypes())) {
return new ArrayType($resultType->getValueTypes()[0], $resultType->getValueTypes()[1]);
} elseif ('fetchSingle' === $methodName && $resultType instanceof ConstantArrayType && 1 === \count($resultType->getValueTypes())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function specifyTypes(MethodReflection $methodReflection, MethodCall $nod
}

if (null !== $inferredType) {
return $this->typeSpecifier->create($methodCall->var, $inferredType, TypeSpecifierContext::createTruthy(), true);
return $this->typeSpecifier->create($methodCall->var, $inferredType, TypeSpecifierContext::createTruthy(), $scope)->setAlwaysOverwriteTypes();
}

return new SpecifiedTypes();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function specifyTypes(MethodReflection $methodReflection, MethodCall $nod
$reducedType = $this->reduceType($methodCall, $statementType, $scope);

if (null !== $reducedType) {
return $this->typeSpecifier->create($methodCall->var, $reducedType, TypeSpecifierContext::createTruthy(), true);
return $this->typeSpecifier->create($methodCall->var, $reducedType, TypeSpecifierContext::createTruthy(), $scope)->setAlwaysOverwriteTypes();
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/MysqliReflection/MysqliResultObjectType.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace staabm\PHPStanDba\MysqliReflection;

use PHPStan\TrinaryLogic;
use PHPStan\Type\IsSuperTypeOfResult;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;

Expand Down Expand Up @@ -40,10 +41,10 @@ public function equals(Type $type): bool
return parent::equals($type);
}

public function isSuperTypeOf(Type $type): TrinaryLogic
public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
{
if ($type instanceof self) {
return TrinaryLogic::createFromBoolean(
return IsSuperTypeOfResult::createFromBoolean(
$type->rowType !== null
&& $this->rowType !== null
&& $type->rowType->equals($this->rowType)
Expand Down
5 changes: 3 additions & 2 deletions src/PdoReflection/PdoStatementObjectType.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerRangeType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\IsSuperTypeOfResult;
use PHPStan\Type\MixedType;
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectType;
Expand Down Expand Up @@ -165,10 +166,10 @@ public function equals(Type $type): bool
return parent::equals($type);
}

public function isSuperTypeOf(Type $type): TrinaryLogic
public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
{
if ($type instanceof self) {
return TrinaryLogic::createFromBoolean(
return IsSuperTypeOfResult::createFromBoolean(
$type->fetchType !== null
&& $type->bothType !== null
&& $this->bothType !== null
Expand Down
8 changes: 4 additions & 4 deletions src/QueryReflection/BasePdoQueryReflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
protected const MAX_CACHE_SIZE = 50;

/**
* @var array<string, PDOException|list<ColumnMeta>|null>
* @var array<string, PDOException|array<ColumnMeta>|null>
*/
protected array $cache = [];

Expand All @@ -66,10 +66,10 @@
* @var PDOStatement|null
* @phpstan-ignore-next-line
*/
protected $stmt = null;

Check failure on line 69 in src/QueryReflection/BasePdoQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (reflection replay) (8.1, pdo-mysql, replay)

No error to ignore is reported on line 69.

Check failure on line 69 in src/QueryReflection/BasePdoQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (reflection replay) (8.1, mysqli, replay)

No error to ignore is reported on line 69.

Check failure on line 69 in src/QueryReflection/BasePdoQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, mariadb:latest, mysqli, recording)

No error to ignore is reported on line 69.

Check failure on line 69 in src/QueryReflection/BasePdoQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, mariadb:latest, mysqli, recording)

No error to ignore is reported on line 69.

Check failure on line 69 in src/QueryReflection/BasePdoQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, mariadb:latest, mysqli, recording)

No error to ignore is reported on line 69.

Check failure on line 69 in src/QueryReflection/BasePdoQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, mysql:8.0, pdo-mysql, recording, --health-cmd="mysqladmin ping" --health-interval=1...

No error to ignore is reported on line 69.

Check failure on line 69 in src/QueryReflection/BasePdoQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, mysql:8.0, mysqli, replay-and-recording, --health-cmd="mysqladmin ping" --health-in...

No error to ignore is reported on line 69.

Check failure on line 69 in src/QueryReflection/BasePdoQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, mysql:8.0, mysqli, recording)

No error to ignore is reported on line 69.

Check failure on line 69 in src/QueryReflection/BasePdoQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, mysql:8.0, pdo-mysql, recording, --health-cmd="mysqladmin ping" --health-interval=1...

No error to ignore is reported on line 69.

Check failure on line 69 in src/QueryReflection/BasePdoQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, mysql:8.0, mysqli, recording)

No error to ignore is reported on line 69.

Check failure on line 69 in src/QueryReflection/BasePdoQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, mysql:8.0, mysqli, recording)

No error to ignore is reported on line 69.

/**
* @var array<string, array<string, list<string>>>
* @var array<string, array<string, array<string>>>
*/
protected array $emulatedFlags = [];

Expand Down Expand Up @@ -138,7 +138,7 @@
}

/**
* @return list<string>
* @return array<string>
*/
protected function emulateFlags(string $nativeType, string $tableName, string $columnName): array
{
Expand Down Expand Up @@ -175,7 +175,7 @@
}

/**
* @return PDOException|list<ColumnMeta>|null
* @return PDOException|array<ColumnMeta>|null
*/
abstract protected function simulateQuery(string $queryString);

Expand Down
6 changes: 5 additions & 1 deletion src/QueryReflection/MysqliQueryReflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,13 @@
foreach ($result as $val) {
if (
! property_exists($val, 'name')
|| ! is_string($val->name)
|| ! property_exists($val, 'type')
|| ! is_int($val->type)
|| ! property_exists($val, 'flags')
|| ! is_int($val->flags)
|| ! property_exists($val, 'length')
|| ! is_int($val->length)
) {
throw new ShouldNotHappenException();
}
Expand Down Expand Up @@ -127,7 +131,7 @@
}

/**
* @return mysqli_sql_exception|list<object>|null
* @return mysqli_sql_exception|array<object>|null
*/
private function simulateQuery(string $queryString)
{
Expand Down Expand Up @@ -169,7 +173,7 @@
}
}

public function getDatasource()

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (reflection replay) (8.1, pdo-mysql, replay)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns PDO so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (reflection replay) (8.1, pdo-mysql, replay)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns null so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (reflection replay) (8.1, mysqli, replay)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns PDO so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (reflection replay) (8.1, mysqli, replay)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns null so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, mariadb:latest, mysqli, recording)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns PDO so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, mariadb:latest, mysqli, recording)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns null so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, mariadb:latest, mysqli, recording)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns PDO so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, mariadb:latest, mysqli, recording)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns null so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, mariadb:latest, mysqli, recording)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns PDO so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, mariadb:latest, mysqli, recording)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns null so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, mysql:8.0, pdo-mysql, recording, --health-cmd="mysqladmin ping" --health-interval=1...

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns PDO so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, mysql:8.0, pdo-mysql, recording, --health-cmd="mysqladmin ping" --health-interval=1...

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns null so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, mysql:8.0, mysqli, replay-and-recording, --health-cmd="mysqladmin ping" --health-in...

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns PDO so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, mysql:8.0, mysqli, replay-and-recording, --health-cmd="mysqladmin ping" --health-in...

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns null so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, mysql:8.0, mysqli, recording)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns PDO so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, mysql:8.0, mysqli, recording)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns null so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, mysql:8.0, pdo-mysql, recording, --health-cmd="mysqladmin ping" --health-interval=1...

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns PDO so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, mysql:8.0, pdo-mysql, recording, --health-cmd="mysqladmin ping" --health-interval=1...

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns null so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, mysql:8.0, mysqli, recording)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns PDO so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, mysql:8.0, mysqli, recording)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns null so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, mysql:8.0, mysqli, recording)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns PDO so it can be removed from the return type.

Check failure on line 176 in src/QueryReflection/MysqliQueryReflector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, mysql:8.0, mysqli, recording)

Method staabm\PHPStanDba\QueryReflection\MysqliQueryReflector::getDatasource() never returns null so it can be removed from the return type.
{
return $this->db;
}
Expand Down
2 changes: 1 addition & 1 deletion src/QueryReflection/PdoMysqlQueryReflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function __construct(PDO $pdo)
}

/**
* @return PDOException|list<ColumnMeta>|null
* @return PDOException|array<ColumnMeta>|null
*/
protected function simulateQuery(string $queryString)
{
Expand Down
6 changes: 3 additions & 3 deletions src/QueryReflection/PdoPgSqlQueryReflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
use function array_shift;

/**
* @phpstan-type PDOColumnMeta array{name: string, table?: string, native_type: string, len: int, flags: list<string>}
* @phpstan-type PDOColumnMeta array{name: string, table?: string, native_type: string, len: int, flags: array<string>}
*/
final class PdoPgSqlQueryReflector extends BasePdoQueryReflector
{
Expand All @@ -28,9 +28,9 @@ public function __construct(PDO $pdo)
}

/**
* @return PDOException|list<PDOColumnMeta>|null
* @return PDOException|array<PDOColumnMeta>|null
*/
protected function simulateQuery(string $queryString) // @phpstan-ignore-line
protected function simulateQuery(string $queryString)
{
if (\array_key_exists($queryString, $this->cache)) {
return $this->cache[$queryString];
Expand Down
Loading
Loading