Execute SQL bruto usando Doctrine 2


102

Eu quero executar SQL puro usando Doctrine 2

Preciso truncar as tabelas de banco de dados e inicializar tabelas com dados de teste padrão.


2
A propósito, quando eu quero fazer trabalho automatizado de banco de dados, como fazer mysqldumps ou carregar dados de despejos anteriores ou eliminar tabelas, geralmente escrevo um script de shell para esse trabalho e, em seguida, escrevo uma tarefa (ou "comando", na linguagem Symfony2 ) que executa o script de shell. O propósito de um ORM, como eu o entendo, é abstrair o trabalho repetitivo, e se você está fazendo algo como truncar uma mesa, não vejo como faria sentido trazer o Doctrine para o cenário, já que o Doctrine não t tornar essa tarefa mais fácil.
Jason Swett

Respostas:


164

Aqui está um exemplo de consulta bruta no Doctrine 2 que estou fazendo:

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
Boa resposta. Para obter o gerenciador de entidade neste código, você pode usar $ this-> getDoctrine () -> getManager () no lugar deste código acima de "$ this-> getEntityManager ()" , dessa forma funcionou para mim imediatamente.
webblover

ei, está me dando Chamada para o método indefinido Index :: getDoctrine () o que devo fazer
Dexter

estou usando codeigniter com a doutrina 2 wildlyinaccurate.com/integrating-doctrine-2-with-codeigniter-2
Dexter

1
Isso me levou na direção certa, mas não era exatamente o que eu precisava. Suspeito que a idade da resposta faz diferença. Eu usei: ...getConnection()->query($sql);e não precisei correr$stmt->execute();
Brandon

Observe que com Symfony4 e autowiring, você pode digitar hint EntityManagerInterface $entityManagere então ligar para$entityManager->getConnection()
COil

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

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

18
Também é uma boa ideia chamar prepare () em vez de exec para que você ainda possa obter o suporte de instrução preparada.
Jeremy Hicks

44

Eu comecei a trabalhar fazendo isso, supondo que você esteja 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);

Você pode alterar o FETCH_TYPE para atender às suas necessidades.


1
O melhor exemplo de todos eles
David

14

Como executar uma consulta bruta e retornar os dados.

Conecte-se ao seu gerente e faça uma nova conexão:

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

Crie sua consulta e fetchAll:

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

Obtenha os dados do resultado como este:

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

1
query () é para quando o SQL retorna alguns dados que você deseja usar; exec () é para quando isso não acontece
Jeffiekins

12

Descobri que a resposta é provavelmente:

Uma NativeQuery permite executar SQL nativo, mapeando os resultados de acordo com suas especificações. Tal especificação que descreve como um conjunto de resultados SQL é mapeado para um resultado Doctrine é representado por um ResultSetMapping.

Fonte: SQL nativo .


17
Essa é a resposta aceita, mas ainda não vejo como essa parte do Doctrine é útil porque você sempre precisa do ResultSetMapping. Eu não quero mapear os resultados para Entidades ... isso padroniza o ponto de execução de SQL arbitrário!
MikeMurko

2
@MikeMurko Achei esta postagem útil para executar consultas brutas no Doctrine 2: forum.symfony-project.org/viewtopic.php?f=23&t=37872
Jason Swett

Também não-nativo Native SQL não executará cada consulta SQL possível. DELETE / UPDATE / INSERT não funcionará, nem algumas definições de tabelas que não seguem as premissas da doutrina. (Mesa de junção M2M sem ids). Portanto, esta resposta não é universal. Nem deve ser aceito porque INSERTs não funcionam.
przemo_li


5

Em seu modelo, crie a instrução SQL bruta (o exemplo abaixo é um exemplo de um intervalo de datas que tive que usar, mas substituir o seu. Se você estiver fazendo um SELECT adicione -> fetchall () à chamada execute ().

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

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

    $stmt->execute();

4

Você não pode, o Doctrine 2 não permite consultas brutas. Pode parecer que sim, mas se você tentar algo assim:

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

O Doctrine irá cuspir um erro dizendo que DATE_FORMAT é uma função desconhecida.

Mas meu banco de dados (mysql) conhece essa função, então basicamente o que está acontecendo é que o Doctrine está analisando essa consulta nos bastidores (e nas suas costas) e encontrando uma expressão que ele não entende, considerando a consulta inválida.

Portanto, se, como eu, você quiser ser capaz de simplesmente enviar uma string para o banco de dados e deixá-la lidar com ela (e deixar o desenvolvedor assumir total responsabilidade pela segurança), esqueça.

Claro que você poderia codificar uma extensão para permitir isso de uma forma ou de outra, mas você também pode usar mysqli para fazer isso e deixar o Doctrine com seu negócio ORM.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.