Ejecute SQL sin procesar usando Doctrine 2

102

Quiero ejecutar SQL sin formato usando Doctrine 2

Necesito truncar las tablas de la base de datos e inicializar las tablas con los datos de prueba predeterminados.

Jiew Meng
fuente
2
Por cierto, cuando quiero hacer un trabajo de base de datos automatizado, como hacer mysqldumps o cargar datos de volcados anteriores o eliminar tablas, generalmente escribo un script de shell para ese trabajo y luego escribo una tarea (o "comando", en lenguaje Symfony2 ) que ejecuta el script de shell. El propósito de un ORM, según tengo entendido, es abstraer el trabajo repetitivo, y si estás haciendo algo como truncar una tabla, no veo cómo tendría sentido traer a Doctrine al cuadro, ya que Doctrine no lo hace. Para facilitar esa tarea.
Jason Swett

Respuestas:

164

Aquí hay un ejemplo de una consulta sin formato en Doctrine 2 que estoy haciendo:

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();
}   
Jason Swett
fuente
4
Buena respuesta. Para obtener el administrador de entidades en este código, puede usar $ this-> getDoctrine () -> getManager () en lugar de este código sobre "$ this-> getEntityManager ()" , de esta manera funcionó para mí de inmediato.
webblover
oye, me está dando una llamada al método indefinido Index :: getDoctrine () ¿qué debo hacer
Dexter
Estoy usando codeigniter con doctrine 2 wildlyinaccurate.com/integrating-doctrine-2-with-codeigniter-2
Dexter
1
Esto me llevó en la dirección correcta, pero no era exactamente lo que necesitaba. Sospecho que la edad de la respuesta marca la diferencia. Usé: ...getConnection()->query($sql);y no tuve que correr$stmt->execute();
Brandon
Tenga en cuenta que con Symfony4 y el cableado automático, puede escribir pista EntityManagerInterface $entityManagery luego llamar a$entityManager->getConnection()
COil
50
//$sql - sql statement
//$em - entity manager

$em->getConnection()->exec( $sql );
orourkedd
fuente
18
También es una buena idea llamar a prepare () en lugar de exec para que aún pueda obtener soporte para declaraciones preparadas.
Jeremy Hicks
44

Lo hice funcionar haciendo esto, asumiendo que estás 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);

Puede cambiar el FETCH_TYPE para que se adapte a sus necesidades.

fernandodof
fuente
1
El mejor ejemplo de todos ellos
David
14

Cómo ejecutar una consulta sin procesar y devolver los datos.

Conéctese a su gerente y establezca una nueva conexión:

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

Crea tu consulta y fetchAll:

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

Obtenga los datos del resultado de esta manera:

$this->appendStringToFile("first row foobar is: " . $result[0]['foobar']);
Eric Leschinski
fuente
1
query () es para cuando SQL devuelve algunos datos que desea usar; exec () es para cuando no lo hace
Jeffiekins
12

Descubrí que la respuesta es probablemente:

Un NativeQuery le permite ejecutar SQL nativo, mapeando los resultados de acuerdo con sus especificaciones. Una especificación de este tipo que describe cómo se asigna un conjunto de resultados de SQL a un resultado de Doctrine se representa mediante un ResultSetMapping.

Fuente: SQL nativo .

Jiew Meng
fuente
17
Esta es la respuesta aceptada, pero todavía no veo cómo esta parte de Doctrine es útil porque siempre necesitas ResultSetMapping. No quiero que asigne los resultados a las entidades ... ¡que por defecto es el punto de ejecutar SQL arbitrario!
MikeMurko
2
@MikeMurko Encontré esta publicación útil para ejecutar consultas sin procesar en Doctrine 2: forum.symfony-project.org/viewtopic.php?f=23&t=37872
Jason Swett
Además , el SQL nativo no nativo no ejecutará todas las consultas SQL posibles. BORRAR / ACTUALIZAR / INSERTAR no funcionará, ni algunas definiciones de tablas que no sigan los supuestos de la doctrina. (Mesa de unión M2M sin ids). Entonces esta respuesta no es universal. Tampoco debe aceptarse ya que los INSERTOS no funcionarán.
przemo_li
5

Yo tuve el mismo problema. Desea buscar el objeto de conexión proporcionado por el administrador de la entidad:

$conn = $em->getConnection();

Luego puede consultar / ejecutar directamente contra él:

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

Consulte los documentos del objeto de conexión en http://www.doctrine-project.org/api/dbal/2.0/doctrine/dbal/connection.html

Toby Batch
fuente
5

En su modelo, cree la declaración SQL sin procesar (el ejemplo a continuación es un ejemplo de un intervalo de fechas que tuve que usar, pero sustituya el suyo. Si está haciendo un SELECT, agregue -> fetchall () a la llamada execute ().

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

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

    $stmt->execute();
badzilla
fuente
4

No puedes, Doctrine 2 no permite consultas sin formato. Puede parecer que puede, pero si intenta algo como esto:

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

Doctrine escupirá un error diciendo que DATE_FORMAT es una función desconocida.

Pero mi base de datos (mysql) sí conoce esa función, así que básicamente lo que está sucediendo es que Doctrine está analizando esa consulta detrás de escena (y detrás de tu espalda) y encuentra una expresión que no comprende, considerando que la consulta no es válida.

Entonces, si, como yo, desea poder simplemente enviar una cadena a la base de datos y dejar que se ocupe de ella (y dejar que el desarrollador asuma toda la responsabilidad por la seguridad), olvídelo.

Por supuesto, podría codificar una extensión para permitir eso de una forma u otra, pero es mejor usar mysqli para hacerlo y dejar Doctrine a su negocio ORM.

Alexis Finn
fuente