phpstan-dba
phpstan-dba copied to clipboard
Using with doctrine/dbal
I try to configure in project with doctrine/dbal. I create a bootstrap:
<?php
declare(strict_types=1);
use Doctrine\DBAL\Connection;
use OndraM\CiDetector\CiDetector;
use Psr\Container\ContainerInterface;
use staabm\PHPStanDba\DbSchema\SchemaHasherMysql;
use staabm\PHPStanDba\QueryReflection\PdoMysqlQueryReflector;
use staabm\PHPStanDba\QueryReflection\QueryReflection;
use staabm\PHPStanDba\QueryReflection\ReflectionCache;
use staabm\PHPStanDba\QueryReflection\ReplayAndRecordingQueryReflector;
use staabm\PHPStanDba\QueryReflection\ReplayQueryReflector;
use staabm\PHPStanDba\QueryReflection\RuntimeConfiguration;
require_once __DIR__ . '/../vendor/autoload.php';
$cacheFile = __DIR__ . '/../data/cache/.phpstan-dba.cache';
$reflectionCache = ReflectionCache::create($cacheFile);
$isCi = ! (new CiDetector())->isCiDetected();
$runtimeConfiguration = new RuntimeConfiguration();
if (! $isCi) {
$runtimeConfiguration->debugMode(true);
$runtimeConfiguration->analyzeQueryPlans();
// $runtimeConfiguration->utilizeSqlAst(true);
/** @var ContainerInterface $container */
$container = require __DIR__ . '/container.php';
/** @var Connection $connection */
$connection = $container->get(Connection::class);
$nativeConnection = $connection->getNativeConnection();
} else {
print PHP_EOL . PHP_EOL . 'CI detected' . PHP_EOL . PHP_EOL;
}
$queryReflector = $isCi
? new ReplayQueryReflector($reflectionCache)
: new ReplayAndRecordingQueryReflector(
$reflectionCache,
new PdoMysqlQueryReflector($nativeConnection),
new SchemaHasherMysql($nativeConnection),
);
QueryReflection::setupReflector($queryReflector, $runtimeConfiguration);
An locally everything works fine. But when I run phpstan on CI, then I get many errors where I use Doctrine\DBAL\Connection::delete or Doctrine\DBAL\Connection::insert
Query error: Table "table_name" does not exist
Did you setup a database server in CI and imported a db schema into a database?
Could you reproduce your problem in a small example repository?
No, but I manage that I don't need do that because I use cache from https://github.com/staabm/phpstan-dba/blob/main/docs/record-and-replay.md
ok this means we can close here?
So I need to setup db? What about this https://github.com/staabm/phpstan-dba/blob/main/docs/record-and-replay.md ?
ohh I missunderstood your previous comment.
record-and-replay can be used for cases when you really cannot setup a DB in CI. you would commit the recorded files into the repo and it should work then.
having a real db and a real schema might be more work, but is more accurate for the analysis - in case you managed a good dev process how you handle db migrations etc.
For me works like you mentioned, but looks like just Doctrine\DBAL\Connection::delete or Doctrine\DBAL\Connection::insert didn't work when run on CI without DB with record-and-replay. There are not errors with missing table or connection when analyse raw SQL queries.
would be great if you would post a full example, which shows what does not work and what you expect
I have simplified code.
final readonly class Db
{
public function __construct(private \Doctrine\DBAL\Connection $connection)
{
}
public function save(
string $id,
): string {
$this->connection->insert('table', [
'id' => $id,
]);
return $this->connection->executeQuery('SELECT id FROM id = :id', [
'id' => $id,
])->fetchOne();
}
}
When I run on local with db with all correct loaded schema, then I use ReplayAndRecordingQueryReflector and phpstan analyse pass.
When I run on CI without db, then I use ReplayQueryReflector and phpstan analyse fail only on insert (Query error: Table "table" does not exist). Analyse on executeQuery looks like working with cache. Cache from dev env is commited to be using on CI.
I always run with bootstrap file from first message. $isCi choose a correct QueryReflector.