Exécuter du SQL brut à l'aide de Doctrine 2


102

Je veux exécuter du SQL brut en utilisant Doctrine 2

Je dois tronquer les tables de la base de données et initialiser les tables avec les données de test par défaut.


2
À propos, lorsque je veux faire du travail de base de données automatisé, comme faire des mysqldumps ou charger des données à partir de vidages précédents ou de supprimer des tables, j'écris généralement un script shell pour ce travail, puis j'écris une tâche (ou "commande", en langage Symfony2 ) qui exécute le script shell. Le but d'un ORM, tel que je le comprends, est d'abstraire le travail répétitif, et si vous faites quelque chose comme tronquer un tableau, je ne vois pas en quoi il serait logique de mettre la Doctrine en scène puisque la Doctrine ne le fait pas. t rendre cette tâche plus facile.
Jason Swett

Réponses:


164

Voici un exemple de requête brute dans Doctrine 2 que je fais:

public function getAuthoritativeSportsRecords()
{   
    $sql = " 
        SELECT name,
               event_type,
               sport_type,
               level
          FROM vnn_sport
    ";

    $em = $this->getDoctrine()->getManager();
    $stmt = $em->getConnection()->prepare($sql);
    $stmt->execute();
    return $stmt->fetchAll();
}   

4
Bonne réponse. Pour obtenir le gestionnaire d'entités dans ce code, vous pouvez utiliser $ this-> getDoctrine () -> getManager () à la place de ce code au-dessus de "$ this-> getEntityManager ()" , de cette façon cela a fonctionné pour moi tout de suite.
webblover

hey, ça me donne Appel à la méthode indéfinie Index :: getDoctrine () que dois-je faire
Dexter


1
Cela m'a conduit dans la bonne direction mais ce n'était pas exactement ce dont j'avais besoin. Je soupçonne que l'âge de la réponse fait une différence. J'ai utilisé: ...getConnection()->query($sql);et je n'ai pas eu à courir$stmt->execute();
Brandon

Notez qu'avec Symfony4 et l'autowiring, vous pouvez taper un indice EntityManagerInterface $entityManagerpuis appeler$entityManager->getConnection()
COil

50
//$sql - sql statement
//$em - entity manager

$em->getConnection()->exec( $sql );

18
Aussi une bonne idée d'appeler prepare () au lieu d'exec afin de pouvoir toujours obtenir le support des instructions préparées.
Jeremy Hicks

44

Je l'ai fait fonctionner en faisant cela, en supposant que vous utilisez PDO.

//Place query here, let's say you want all the users that have blue as their favorite color
$sql = "SELECT name FROM user WHERE favorite_color = :color";

//set parameters 
//you may set as many parameters as you have on your query
$params['color'] = blue;


//create the prepared statement, by getting the doctrine connection
$stmt = $this->entityManager->getConnection()->prepare($sql);
$stmt->execute($params);
//I used FETCH_COLUMN because I only needed one Column.
return $stmt->fetchAll(PDO::FETCH_COLUMN);

Vous pouvez modifier le FETCH_TYPE en fonction de vos besoins.


1
Meilleur exemple de tous
David

14

Comment exécuter une requête brute et renvoyer les données.

Accrochez-vous à votre manager et établissez une nouvelle connexion:

$manager = $this->getDoctrine()->getManager();
$conn = $manager->getConnection();

Créez votre requête et fetchAll:

$result= $conn->query('select foobar from mytable')->fetchAll();

Obtenez les données du résultat comme ceci:

$this->appendStringToFile("first row foobar is: " . $result[0]['foobar']);

1
query () est utilisé lorsque le SQL renvoie certaines données que vous souhaitez utiliser; exec () est pour quand ce n'est pas le cas
Jeffiekins

12

J'ai découvert que la réponse est probablement:

Un NativeQuery vous permet d'exécuter du SQL natif, en mappant les résultats selon vos spécifications. Une telle spécification qui décrit comment un jeu de résultats SQL est mappé à un résultat Doctrine est représentée par un ResultSetMapping.

Source: SQL natif .


17
C'est la réponse acceptée mais je ne vois toujours pas en quoi cette partie de Doctrine est utile car vous avez toujours besoin du ResultSetMapping. Je ne veux pas qu'il mappe les résultats aux entités .... qui par défaut le point d'exécuter SQL arbitraire!
MikeMurko

2
@MikeMurko J'ai trouvé ce post utile pour exécuter des requêtes brutes dans Doctrine 2: forum.symfony-project.org/viewtopic.php?f=23&t=37872
Jason Swett

De plus, le SQL natif non natif n'exécutera pas toutes les requêtes SQL possibles. DELETE / UPDATE / INSERT ne fonctionnera pas, ni certaines définitions de table qui ne suivent pas les hypothèses de doctrine. (Table de jonction M2M sans ID). Cette réponse n'est donc pas universelle. Il ne devrait pas non plus être accepté car les INSERT ne fonctionneront pas.
przemo_li


5

Dans votre modèle, créez l'instruction SQL brute (l'exemple ci-dessous est un exemple d'intervalle de date que j'ai dû utiliser mais que je remplace le vôtre. Si vous effectuez un SELECT, ajoutez -> fetchall () à l'appel execute ().

   $sql = "DELETE FROM tmp 
            WHERE lastedit + INTERVAL '5 minute' < NOW() ";

    $stmt = $this->getServiceLocator()
                 ->get('Doctrine\ORM\EntityManager')
                 ->getConnection()
                 ->prepare($sql);

    $stmt->execute();

4

Vous ne pouvez pas, Doctrine 2 ne permet pas les requêtes brutes. Cela peut sembler possible, mais si vous essayez quelque chose comme ceci:

$sql = "SELECT DATE_FORMAT(whatever.createdAt, '%Y-%m-%d') FORM whatever...";
$em = $this->getDoctrine()->getManager();
$em->getConnection()->exec($sql);

La doctrine crachera une erreur disant que DATE_FORMAT est une fonction inconnue.

Mais ma base de données (mysql) connaît cette fonction, donc fondamentalement, ce qui se passe, c'est que Doctrine analyse cette requête dans les coulisses (et derrière votre dos) et trouve une expression qu'elle ne comprend pas, considérant que la requête est invalide.

Donc, si comme moi vous voulez pouvoir simplement envoyer une chaîne à la base de données et la laisser s'en occuper (et laisser le développeur prendre l'entière responsabilité de la sécurité), oubliez-la.

Bien sûr, vous pouvez coder une extension pour autoriser cela d'une manière ou d'une autre, mais vous pouvez tout aussi bien utiliser mysqli pour le faire et laisser Doctrine à son activité ORM.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.