Wykonaj surowy SQL za pomocą Doctrine 2

102

Chcę wykonać surowy SQL za pomocą Doctrine 2

Muszę obciąć tabele bazy danych i zainicjować tabele z domyślnymi danymi testowymi.

Jiew Meng
źródło
2
Nawiasem mówiąc, kiedy chcę wykonać zautomatyzowaną pracę bazy danych, taką jak robienie mysqldumps lub ładowanie danych z poprzednich zrzutów lub upuszczanie tabel, zwykle piszę skrypt powłoki dla tej pracy, a następnie piszę zadanie (lub "polecenie" w języku Symfony2 ), który wykonuje skrypt powłoki. Celem ORM, jak rozumiem, jest oderwanie od powtarzalnej pracy, a jeśli robisz coś takiego, jak obcinanie tabeli, nie widzę sensu, aby wprowadzić Doktrynę na obraz, skoro Doktryna tego nie robi. Ułatw sobie to zadanie.
Jason Swett

Odpowiedzi:

164

Oto przykład surowego zapytania w Doctrine 2, które robię:

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
źródło
4
Niezła odpowiedź. Aby uzyskać menedżera encji w tym kodzie, możesz użyć $ this-> getDoctrine () -> getManager () zamiast tego kodu powyżej "$ this-> getEntityManager ()" , w ten sposób zadziałało to od razu.
webblover
hej, to daje mi wywołanie niezdefiniowanej metody Index :: getDoctrine () co mam zrobić
Dexter
używam codeigniter z doktryną 2 wildlyinaccurate.com/integrating-doctrine-2-with-codeigniter-2
Dexter,
1
To poprowadziło mnie we właściwym kierunku, ale nie było to dokładnie to, czego potrzebowałem. Podejrzewam, że wiek odpowiedzi ma znaczenie. Użyłem: ...getConnection()->query($sql);i nie musiałem biec$stmt->execute();
Brandon
Zauważ, że z Symfony4 i autowiring, możesz wpisać podpowiedź, EntityManagerInterface $entityManagera następnie zadzwonić$entityManager->getConnection()
COil.
50
//$sql - sql statement
//$em - entity manager

$em->getConnection()->exec( $sql );
orourkedd
źródło
18
Dobrym pomysłem jest również wywołanie funkcji przygotowywania () zamiast exec, aby nadal można było uzyskać obsługę przygotowanych instrukcji.
Jeremy Hicks
44

Udało mi się to zrobić, zakładając, że używasz 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);

Możesz zmienić FETCH_TYPE zgodnie ze swoimi potrzebami.

fernandodof
źródło
1
Najlepszy przykład z nich wszystkich
David
14

Jak wykonać nieprzetworzone zapytanie i zwrócić dane.

Połącz się ze swoim menedżerem i nawiąż nowe połączenie:

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

Utwórz zapytanie i pobierz wszystko:

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

Uzyskaj dane z wyniku w następujący sposób:

$this->appendStringToFile("first row foobar is: " . $result[0]['foobar']);
Eric Leschinski
źródło
1
query () służy do zwracania przez SQL pewnych danych, których chcesz użyć; exec () jest
używana,
12

Dowiedziałem się, że odpowiedź brzmi prawdopodobnie:

NativeQuery umożliwia wykonywanie natywnego kodu SQL, mapując wyniki zgodnie ze specyfikacjami. Taka specyfikacja, która opisuje, w jaki sposób zestaw wyników SQL jest odwzorowywany na wynik Doctrine, jest reprezentowana przez element ResultSetMapping.

Źródło: Native SQL .

Jiew Meng
źródło
17
To jest akceptowana odpowiedź, ale nadal nie widzę użyteczności tej części Doctrine, ponieważ zawsze potrzebujesz ResultSetMapping. Nie chcę, aby odwzorowywał wyniki na encje… co jest domyślnym punktem uruchamiania dowolnego SQL!
MikeMurko
2
@MikeMurko znalazłem ten post pomocne do prowadzenia surowe zapytań w Doctrine 2: forum.symfony-project.org/viewtopic.php?f=23&t=37872
Jason Swett
Również inny niż macierzysty język SQL nie wykona każdego możliwego zapytania SQL. DELETE / UPDATE / INSERT nie zadziała, ani niektóre definicje tabel, które nie są zgodne z założeniami doktryny. (Stół łączący M2M bez identyfikatorów). Więc ta odpowiedź nie jest uniwersalna. Nie należy też akceptować, ponieważ WSTAWKI nie będą działać.
przemo_li
5

Miałem ten sam problem. Chcesz spojrzeć na obiekt połączenia dostarczony przez menedżera encji:

$conn = $em->getConnection();

Następnie możesz zapytać / wykonać bezpośrednio przeciwko niemu:

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

Zobacz dokumentację obiektu połączenia pod adresem http://www.doctrine-project.org/api/dbal/2.0/doctrine/dbal/connection.html

Toby Batch
źródło
5

W swoim modelu utwórz surową instrukcję SQL (poniższy przykład to przykład przedziału czasu, którego musiałem użyć, ale zastąp własny. Jeśli wykonujesz polecenie SELECT dodaj -> fetchall () do wywołania execute ().

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

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

    $stmt->execute();
badzilla
źródło
4

Nie możesz, Doctrine 2 nie zezwala na nieprzetworzone zapytania. Może się wydawać, że możesz, ale jeśli spróbujesz czegoś takiego:

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

Doctrine wypluje błąd informujący, że DATE_FORMAT to nieznana funkcja.

Ale moja baza danych (mysql) zna tę funkcję, więc w zasadzie Doctrine analizuje to zapytanie za kulisami (i za twoimi plecami) i znajduje wyrażenie, którego nie rozumie, uznając zapytanie za nieprawidłowe.

Więc jeśli tak jak ja chcesz móc po prostu wysłać ciąg do bazy danych i pozwolić jej się tym zająć (i pozwolić programistom wziąć pełną odpowiedzialność za bezpieczeństwo), zapomnij o tym.

Oczywiście możesz zakodować rozszerzenie, które pozwoli na to w jakiś sposób, ale równie dobrze możesz użyć mysqli, aby to zrobić i pozostawić Doctrine firmie ORM.

Alexis Finn
źródło