Führen Sie Raw SQL mit Doctrine 2 aus


102

Ich möchte Raw SQL mit Doctrine 2 ausführen

Ich muss die Datenbanktabellen abschneiden und Tabellen mit Standardtestdaten initialisieren.


2
Übrigens, wenn ich automatisierte Datenbank-Grunzarbeiten ausführen möchte, z. B. mysqldumps oder das Laden von Daten aus früheren Dumps oder das Löschen von Tabellen, schreibe ich normalerweise ein Shell-Skript für diese Arbeit und schreibe dann eine Aufgabe (oder einen "Befehl") in Symfony2-Sprache ), das das Shell-Skript ausführt. Der Zweck eines ORM besteht meines Wissens darin, sich wiederholende Arbeiten zu abstrahieren, und wenn Sie so etwas wie das Abschneiden einer Tabelle tun, sehe ich keinen Sinn darin, Doctrine ins Bild zu bringen, da Doctrine dies nicht tut. t diese Aufgabe nicht einfacher machen.
Jason Swett

Antworten:


164

Hier ist ein Beispiel für eine Rohabfrage in Lehre 2, die ich mache:

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
Gute Antwort. Um den Entity Manager in diesen Code zu integrieren, können Sie $ this-> getDoctrine () -> getManager () anstelle dieses Codes über "$ this-> getEntityManager ()" verwenden . Auf diese Weise hat es sofort für mich funktioniert.
Webblover

Hey, es gibt mir Aufruf der undefinierten Methode Index :: getDoctrine () Was soll ich tun
Dexter


1
Dies führte mich in die richtige Richtung, war aber nicht genau das, was ich brauchte. Ich vermute, dass das Alter der Antwort einen Unterschied macht. Ich benutzte: ...getConnection()->query($sql);und musste nicht rennen$stmt->execute();
Brandon

Beachten Sie, dass Sie mit Symfony4 und Autowiring einen Hinweis EntityManagerInterface $entityManager$entityManager->getConnection()
eingeben

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

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

18
Es ist auch eine gute Idee, prepare () anstelle von exec aufzurufen, damit Sie weiterhin Unterstützung für vorbereitete Anweisungen erhalten.
Jeremy Hicks

44

Ich habe es auf diese Weise zum Laufen gebracht, vorausgesetzt, Sie verwenden 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);

Sie können FETCH_TYPE an Ihre Bedürfnisse anpassen.


1
Bestes Beispiel von allen
David

14

So führen Sie eine Rohabfrage aus und geben die Daten zurück.

Schließen Sie Ihren Manager an und stellen Sie eine neue Verbindung her:

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

Erstellen Sie Ihre Abfrage und fetchAll:

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

Holen Sie sich die Daten aus dem Ergebnis wie folgt:

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

1
query () ist für den Fall vorgesehen, dass SQL einige Daten zurückgibt, die Sie verwenden möchten. exec () ist für, wenn es nicht tut
Jeffiekins

12

Ich fand heraus, dass die Antwort wahrscheinlich ist:

Mit einer NativeQuery können Sie natives SQL ausführen und die Ergebnisse gemäß Ihren Spezifikationen zuordnen. Eine solche Spezifikation, die beschreibt, wie eine SQL-Ergebnismenge einem Doctrine-Ergebnis zugeordnet wird, wird durch eine ResultSetMapping dargestellt.

Quelle: Native SQL .


17
Dies ist die akzeptierte Antwort, aber ich sehe immer noch nicht, wie nützlich dieser Teil von Doctrine ist, da Sie immer das ResultSetMapping benötigen. Ich möchte nicht, dass die Ergebnisse Entitäten zugeordnet werden ... das ist standardmäßig der Punkt, an dem beliebiges SQL ausgeführt wird!
Mike Murko

2
@ MikeMurko Ich fand diesen Beitrag hilfreich für die Ausführung von Rohabfragen
Jason Swett

Auch nicht natives natives SQL führt nicht jede mögliche SQL-Abfrage aus. DELETE / UPDATE / INSERT funktioniert nicht und einige Tabellendefinitionen, die nicht den Annahmen der Doktrin entsprechen. (M2M-Verbindungstabelle ohne IDs). Diese Antwort ist also nicht universell. Es sollte auch nicht akzeptiert werden, da INSERTs nicht funktionieren.
przemo_li

5

Ich hatte das gleiche Problem. Sie möchten das vom Entitätsmanager bereitgestellte Verbindungsobjekt anzeigen:

$conn = $em->getConnection();

Sie können dann direkt danach abfragen / ausführen:

$statement = $conn->query('select foo from bar');
$num_rows_effected = $conn->exec('update bar set foo=1');

Weitere Informationen zum Verbindungsobjekt finden Sie in den Dokumenten unter http://www.doctrine-project.org/api/dbal/2.0/doctrine/dbal/connection.html


5

Erstellen Sie in Ihrem Modell die SQL-Rohanweisung (Beispiel unten ist ein Beispiel für ein Datumsintervall, das ich verwenden musste, aber ersetzen Sie Ihr eigenes. Wenn Sie SELECT ausführen, fügen Sie dem Aufruf execute ()> fetchall () hinzu.

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

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

    $stmt->execute();

4

Sie können nicht, Doctrine 2 erlaubt keine rohen Abfragen. Es mag so aussehen, als könnten Sie es, aber wenn Sie so etwas versuchen:

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

Doctrine gibt einen Fehler aus, der besagt, dass DATE_FORMAT eine unbekannte Funktion ist.

Aber meine Datenbank (mysql) kennt diese Funktion. Im Grunde genommen ist es also Doctrine, diese Abfrage hinter den Kulissen (und hinter Ihrem Rücken) zu analysieren und einen Ausdruck zu finden, den sie nicht versteht, da die Abfrage ungültig ist.

Wenn Sie also wie ich in der Lage sein möchten, einfach eine Zeichenfolge an die Datenbank zu senden und sie damit umgehen zu lassen (und den Entwickler die volle Verantwortung für die Sicherheit übernehmen zu lassen), vergessen Sie dies.

Natürlich könnten Sie eine Erweiterung codieren, um dies auf die eine oder andere Weise zu ermöglichen, aber Sie sollten genauso gut mysqli verwenden, um dies zu tun, und Doctrine dem ORM-Geschäft überlassen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.