staabm / phpstan-dba

PHPStan based SQL static analysis and type inference for the database access layer
https://staabm.github.io/archive.html#phpstan-dba
MIT License
252 stars 17 forks source link

Support for custom API's for type inference #635

Open ArtemGoutsoul opened 10 months ago

ArtemGoutsoul commented 10 months ago

I use laminas-db (https://docs.laminas.dev/laminas-db/) wrapper, mostly with raw, dynamically assembled queries with different fetch modes, and it would be really cool if it was possible to infer result types for themn.

Here are some examples:

$db = MyDb::new($config); // MyDb is my wrapper adound laminas-db

// suppose table1 has columns column1, column2 (nullable), column3, column4

// should return for example
// @var $r list<array{column1: string, column2: string|null}>
$r = $db->fetchAll("
    SELECT column1, column2 FROM table1 WHERE column3 = :column3 AND column4 = :column4
    ", ['column3' => 'some value 2','column4' => 'some value 2']);

// should return for example
// @var $r array<string, array{column1: string, column2: string|null, column3: string}>
$r = $db->fetchAssoc("
    SELECT column1, column2, column3 FROM table1 WHERE column3 = :column3 OR column4 = :column4
    ", ['column3' => 'some value 2','column4' => 'some value 2']);

// should return for example
// @var $r array{column1: string, column2: string|null}
$r = $db->getRow("
    SELECT column1, column2 FROM table1 WHERE column3 = :column3 AND column4 = :column4
    ", ['column3' => 'some value 2','column4' => 'some value 2']);

// should return for example
// @var $r array<string, string|null>
$r = $db->fetchPairs("
    SELECT column1, column2 FROM table1 WHERE column3 = :column3 AND column4 = :column4
    ", ['column3' => 'some value 2','column4' => 'some value 2']);

These methods could be configured similarly to the query syntax analysis: https://github.com/staabm/phpstan-dba/blob/main/docs/rules.md

Ideally the return type would be an intersection with the existing method type inferred by phpstan. That type is correct but too wide.

staabm commented 9 months ago

I think db apis have subtle differences and therefore re-using a single extension is most of the time not possible.

but you could built your own PHPStan return type extension for your DBLayer, based on the API phpstan-dba provides you.

similar to https://github.com/staabm/phpstan-dba/blob/main/src/Extensions/DoctrineConnectionFetchDynamicReturnTypeExtension.php