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.


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();
}   

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


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 );

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.


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']);

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 .


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

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();

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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.