SQL dans un repository
Comment utiliser le langage SQL dans une méthode d'un repository pour faire des requêtes dans la base de données
Notions théoriques
Bien que Doctrine offre des méthodes puissantes pour interroger la base de données, il peut parfois être nécessaire d'écrire des requêtes SQL brutes pour des cas d'utilisation spécifiques ou pour des raisons de performance.
Symfony permet d'exécuter facilement des requêtes SQL personnalisées au sein d'un repository.
Les principales raisons d'utiliser du SQL brut sont :
- Optimisation des performances pour des requêtes simples
- Utilisation de fonctions spécifiques à la base de données
- Exécution de requêtes qui ne correspondent pas au modèle objet de Doctrine
Exemple
Voici un exemple de requête dans la base de données en utilisant DQL (Doctrine Query Language) dans un repository Symfony :
use App\Entity\Player;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
class PlayerRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Player::class);
}
public function findTopPlayers($limit = 10)
{
$entityManager = $this->getEntityManager();
$dql = "SELECT p.id, p.name, p.score
FROM App\Entity\Player p
ORDER BY p.score DESC";
$query = $entityManager->createQuery($dql)
->setMaxResults($limit);
return $query->getResult();
}
}
Etudions ce code DQL
$entityManager = $this->getEntityManager();
Nous récupérons l'EntityManager directement depuis le repository.
$dql = "SELECT p.id, p.name, p.score
FROM App\Entity\Player p
ORDER BY p.score DESC";
Nous définissons notre requête DQL. Notez que nous utilisons le nom complet de l'entité (App\Entity\Player
) et un alias (p
). La syntaxe est très similaire à SQL, mais nous travaillons avec des entités plutôt que des tables.
$query = $entityManager->createQuery($dql)
->setMaxResults($limit);
Nous créons la requête à partir du DQL et définissons le nombre maximum de résultats avec setMaxResults()
. C'est l'équivalent de LIMIT
en SQL.
return $query->getResult();
Nous exécutons la requête et retournons les résultats.
Par défaut, getResult()
retourne un tableau d'objets hydratés (dans ce cas, des objets partiels contenant seulement id, name et score).
L'avantage de DQL est qu'il est indépendant de la base de données et travaille directement avec les entités. Il offre également une meilleure intégration avec l'ORM Doctrine, permettant par exemple de retourner facilement des objets hydratés plutôt que de simples tableaux associatifs.
La même chose en SQL
Il est parfois nécessaire (ou plus simple) d'écrire sa requête au format SQL.
Voici un exemple de repository utilisant une requête SQL brute simple dans Symfony :
use App\Entity\Player;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\ORM\EntityManagerInterface;
class PlayerRepository extends ServiceEntityRepository
{
private $entityManager;
public function __construct(ManagerRegistry $registry, EntityManagerInterface $entityManager)
{
parent::__construct($registry, Player::class);
$this->entityManager = $entityManager;
}
public function findTopPlayers($limit = 10)
{
$conn = $this->entityManager->getConnection();
$sql = '
SELECT id, name, score
FROM player
ORDER BY score DESC
LIMIT :limit
';
$stmt = $conn->prepare($sql);
$result = $stmt->executeQuery(['limit' => $limit]);
return $result->fetchAllAssociative();
}
}
Etudions ce code
$conn = $this->entityManager->getConnection();
Cette ligne récupère la connexion à la base de données à partir de l'EntityManager injecté.
$sql = '
SELECT id, name, score
FROM player
ORDER BY score DESC
LIMIT :limit
';
Nous définissons notre requête SQL personnalisée. Elle sélectionne les joueurs, les trie par score décroissant et limite le nombre de résultats.
$stmt = $conn->prepare($sql);
$result = $stmt->executeQuery(['limit' => $limit]);
Nous préparons et exécutons la requête en passant le paramètre limit
.
return $result->fetchAllAssociative();
Enfin, nous récupérons tous les résultats sous forme de tableau associatif.
Comparatif DQL / SQL
Voici un comparatif des avantages et inconvénients de DQL (Doctrine Query Language) par rapport à SQL :
Avantages de DQL
-
Indépendance de la base de données : DQL est traduit en SQL spécifique à chaque système de base de données, permettant une portabilité du code entre différents SGBD.
-
Travail avec des objets : DQL manipule directement les entités et leurs propriétés, ce qui s'intègre mieux avec le modèle objet de l'application.
-
Abstraction du schéma : Les requêtes DQL sont indépendantes du schéma de base de données sous-jacent, facilitant les changements de structure sans impacter le code.
-
Sécurité accrue : DQL gère automatiquement l'échappement des paramètres, réduisant les risques d'injection SQL.
-
Intégration avec l'ORM : DQL s'intègre parfaitement avec les fonctionnalités de Doctrine comme le chargement différé (lazy loading) ou le cache.
Inconvénients de DQL
-
Courbe d'apprentissage : DQL nécessite d'apprendre une nouvelle syntaxe, même si elle est proche de SQL.
-
Fonctionnalités limitées : Certaines fonctionnalités avancées de SQL peuvent ne pas être disponibles en DQL.
-
Performance potentiellement moindre : Dans certains cas complexes, les requêtes SQL brutes peuvent être optimisées plus finement que leur équivalent DQL.
Avantages de SQL
-
Contrôle total : SQL offre un contrôle complet sur les requêtes et permet d'utiliser toutes les fonctionnalités spécifiques à la base de données.
-
Performance optimale : Pour des requêtes très complexes, SQL peut offrir de meilleures performances car il est directement exécuté par la base de données.
-
Familiarité : SQL est largement connu et utilisé, facilitant la collaboration entre développeurs et administrateurs de bases de données.
Inconvénients de SQL
-
Dépendance à la base de données : Les requêtes SQL sont souvent spécifiques à un système de base de données particulier, limitant la portabilité.
-
Risques de sécurité : L'utilisation de SQL brut augmente les risques d'injection SQL si les paramètres ne sont pas correctement échappés.
-
Découplage du modèle objet : SQL travaille directement avec les tables et les colonnes, ce qui peut créer un décalage avec le modèle objet de l'application.
En conclusion, DQL est généralement préféré dans le contexte de Doctrine et des applications orientées objet pour sa portabilité et son intégration avec l'ORM, tandis que SQL reste incontournable pour des requêtes très spécifiques ou des optimisations poussées.
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Votre défi pour aujourd'hui consiste à écrire une requête SQL brute dans le repository.
Créez une méthode dans le PlayerRepository
qui utilise une requête SQL brute pour récupérer les joueurs d'une catégorie spécifique, triés par score décroissant.
La méthode doit accepter la catégorie et une limite optionnelle comme paramètres.
Une solution
Vous devez être connecté pour voir le contenu.