Exécuter des requêtes SQL brutes avec Doctrine

Publié le 16/01/2020 • Mis à jour le 16/01/2020


English language detected! 🇬🇧

  We noticed that your browser is using English. Do you want to read this post in this language?

Read the english version 🇬🇧 Close

Dans ce bout de code, nous allons voir comment exécuter des requêtes brutes via l'instance DBAL de Doctrine. Dans le premier exemple, nous préparons une requête et nous lui affectons un paramètre de type entier. Dans le second, comme il n'y pas de paramètre à remplacer, nous pouvons directement utiliser la méthode raccourcie fetchAll pour récupérer des données.


<?php declare(strict_types=1);

// src/Controller/Snippet/Snippet70Trait.php

namespace App\Controller\Snippet;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\ParameterType;
use Symfony\Component\Config\Definition\Exception\InvalidTypeException;

/**
 * J'utilise un trait PHP afin d'isoler chaque snippet dans un fichier.
 * Ce code doit être apellé d'un contrôleur Symfony étendant AbstractController (depuis Symfony 4.2)
 * ou Symfony\Bundle\FrameworkBundle\Controller\Controller (Symfony <= 4.1).
 * Les services sont injectés dans le constructeur du contrôleur principal.
 *
 * @property Connection $connection
 */
trait Snippet70Trait
{
    public function snippet70(): void
    {
        if (!$this->connection instanceof Connection) {
            throw new InvalidTypeException('Doctrine connection is invalid.');
        }

        $sql = 'SELECT type_id, count(*) AS count FROM article WHERE id > ? GROUP BY type_id';
        echo $sql.PHP_EOL.PHP_EOL;

        try {
            $statement = $this->connection->prepare($sql);
        } catch (DBALException $e) {
            throw new \RuntimeException(sprintf('Error while preparing the SQL: %s', $e->getMessage()));
        }

        // Properly replace first placeholder "?" in the SQL by an integer value
        $statement->bindValue(1, 20, ParameterType::INTEGER);
        $statement->execute();
        var_dump($statement->fetchAll()) ;

        $sql2 = 'SELECT type_id, count(*) AS count FROM article GROUP BY type_id';
        echo $sql2.PHP_EOL.PHP_EOL;
        var_dump($this->connection->fetchAll($sql2));

        // That's it! 😁
    }
}

 Exécuter le snippet  ≪ this.showUnitTest ? this.trans.hide_unit_test : this.trans.show_unit_test ≫  Plus sur Stackoverflow   Lire la doc   Lire la doc

<?php declare(strict_types=1);

namespace App\Tests\Controller\Snippets;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\ParameterType;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

/**
 * @covers Snippet70Trait
 */
final class Snippet70Test extends KernelTestCase
{
    private Connection $connection;

    protected function setUp(): void
    {
        self::bootKernel();
        $this->connection = self::$kernel->getContainer()->get('doctrine.dbal.default_connection');
    }

    /**
     * @covers Snippet70Trait::snippet70
     */
    public function testSnippet70(): void
    {
        $statement = $this->connection->prepare('SELECT type_id, count(*) AS count FROM article WHERE id > ? GROUP BY type_id');
        $statement->bindValue(1, 20,  ParameterType::INTEGER);
        $statement->execute();
        $res = $statement->fetchAll();
        self::assertIsArray($res);
        self::assertSame(['type_id', 'count'], array_keys($res[0] ?? []));

        $res2 = $this->connection->fetchAll('SELECT type_id, count(*) AS count FROM article GROUP BY type_id');
        self::assertIsArray($res2);
        self::assertSame(['type_id', 'count'], array_keys($res2[0] ?? []));
    }
}