Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using with doctrine/dbal #645

Open
snapshotpl opened this issue Feb 9, 2024 · 8 comments
Open

Using with doctrine/dbal #645

snapshotpl opened this issue Feb 9, 2024 · 8 comments

Comments

@snapshotpl
Copy link

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     
@staabm
Copy link
Owner

staabm commented Feb 9, 2024

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?

@snapshotpl
Copy link
Author

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

@staabm
Copy link
Owner

staabm commented Feb 9, 2024

ok this means we can close here?

@snapshotpl
Copy link
Author

So I need to setup db? What about this https://github.com/staabm/phpstan-dba/blob/main/docs/record-and-replay.md ?

@staabm
Copy link
Owner

staabm commented Feb 9, 2024

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.

@snapshotpl
Copy link
Author

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.

@staabm
Copy link
Owner

staabm commented Feb 9, 2024

would be great if you would post a full example, which shows what does not work and what you expect

@snapshotpl
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants