Esegui SQL raw utilizzando Doctrine 2


102

Voglio eseguire SQL grezzo usando Doctrine 2

Devo troncare le tabelle del database e inizializzare le tabelle con i dati di test predefiniti.


2
A proposito, quando voglio fare gruntwork automatizzato di database, come eseguire so mysqldumpcaricare dati da dump precedenti o rilasciare tabelle, di solito scrivo uno script di shell per quel lavoro e poi scrivo un'attività (o "comando", nel linguaggio Symfony2 ) che esegue lo script di shell. Lo scopo di un ORM, a quanto ho capito, è astrarre il lavoro ripetitivo, e se stai facendo qualcosa come troncare una tabella, non vedo come avrebbe senso portare Doctrine nel quadro poiché Doctrine non lo fa ' t rendere questo compito più facile.
Jason Swett

Risposte:


164

Ecco un esempio di una query grezza in Doctrine 2 che sto facendo:

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
Bella risposta. Per ottenere Entity Manager in questo codice, puoi usare $ this-> getDoctrine () -> getManager () al posto di questo codice sopra "$ this-> getEntityManager ()" , in questo modo ha funzionato immediatamente per me.
webblover

hey mi sta dando una chiamata a un metodo non definito Index :: getDoctrine () cosa dovrei fare
Dexter


1
Questo mi ha portato nella giusta direzione, ma non era esattamente quello di cui avevo bisogno. Ho il sospetto che l'età della risposta faccia la differenza. Ho usato: ...getConnection()->query($sql);e non dovevo correre$stmt->execute();
Brandon il

Nota che con Symfony4 e l'autowiring puoi digitare hint EntityManagerInterface $entityManagere poi chiamare$entityManager->getConnection()
COil

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

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

18
È anche una buona idea chiamare prepare () invece di exec in modo da poter comunque ottenere il supporto per le istruzioni preparate.
Jeremy Hicks

44

L'ho fatto funzionare in questo modo, supponendo che tu stia usando 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);

Puoi modificare FETCH_TYPE in base alle tue esigenze.


1
Il miglior esempio tra tutti loro
David

14

Come eseguire una query non elaborata e restituire i dati.

Collegati al tuo manager e crea una nuova connessione:

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

Crea la tua query e fetchAll:

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

Ottieni i dati dal risultato in questo modo:

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

1
query () è per quando l'SQL restituisce alcuni dati che si desidera utilizzare; exec () è per quando non lo fa
Jeffiekins

12

Ho scoperto che la risposta è probabilmente:

Una NativeQuery ti consente di eseguire SQL nativo, mappando i risultati secondo le tue specifiche. Tale specifica che descrive come un set di risultati SQL viene mappato a un risultato di Doctrine è rappresentata da un ResultSetMapping.

Fonte: SQL nativo .


17
Questa è la risposta accettata, ma ancora non vedo come questa parte di Doctrine sia utile perché hai sempre bisogno di ResultSetMapping. Non voglio che mappi i risultati in Entities .... che imposta come predefinito il punto di esecuzione di SQL arbitrario!
MikeMurko

2
@MikeMurko Ho trovato questo post utile per eseguire query grezze in Doctrine 2: forum.symfony-project.org/viewtopic.php?f=23&t=37872
Jason Swett

Anche l' SQL nativo non nativo non eseguirà tutte le query SQL possibili. DELETE / UPDATE / INSERT non funzionerà, né alcune definizioni di tabella che non seguono i presupposti della dottrina. (Tabella di unione M2M senza ID). Quindi questa risposta non è universale. Né dovrebbe essere accettato in quanto gli INSERT non funzioneranno.
przemo_li

5

Ho avuto lo stesso problema. Vuoi guardare l'oggetto connessione fornito dal gestore entità:

$conn = $em->getConnection();

È quindi possibile eseguire query / eseguire direttamente su di esso:

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

Vedere la documentazione per l'oggetto connessione su http://www.doctrine-project.org/api/dbal/2.0/doctrine/dbal/connection.html


5

Nel tuo modello crea l'istruzione SQL grezza (l'esempio sotto è un esempio di un intervallo di date che ho dovuto usare ma ho sostituito il tuo. Se stai facendo un SELECT aggiungi -> fetchall () alla chiamata execute ().

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

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

    $stmt->execute();

4

Non puoi, Doctrine 2 non consente query grezze. Può sembrare che tu possa farlo, ma se provi qualcosa del genere:

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

Doctrine sputerà un errore dicendo che DATE_FORMAT è una funzione sconosciuta.

Ma il mio database (mysql) conosce quella funzione, quindi fondamentalmente ciò che sta accadendo è che Doctrine sta analizzando quella query dietro le quinte (e alle tue spalle) e trova un'espressione che non comprende, considerando la query non valida.

Quindi, se come me vuoi essere in grado di inviare semplicemente una stringa al database e lasciare che se ne occupi (e lasciare che lo sviluppatore si assuma la piena responsabilità della sicurezza), dimenticalo.

Ovviamente potresti codificare un'estensione per consentirlo in un modo o nell'altro, ma altrettanto bene usare mysqli per farlo e lasciare Doctrine ai suoi affari ORM.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.