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.