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ę:
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ć
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()
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.
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.
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!
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');
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();
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.
mysqldump
s 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.Odpowiedzi:
Oto przykład surowego zapytania w Doctrine 2, które robię:
źródło
...getConnection()->query($sql);
i nie musiałem biec$stmt->execute();
EntityManagerInterface $entityManager
a następnie zadzwonić$entityManager->getConnection()
źródło
Udało mi się to zrobić, zakładając, że używasz PDO.
Możesz zmienić FETCH_TYPE zgodnie ze swoimi potrzebami.
źródło
Jak wykonać nieprzetworzone zapytanie i zwrócić dane.
Połącz się ze swoim menedżerem i nawiąż nowe połączenie:
Utwórz zapytanie i pobierz wszystko:
Uzyskaj dane z wyniku w następujący sposób:
źródło
Dowiedziałem się, że odpowiedź brzmi prawdopodobnie:
Źródło: Native SQL .
źródło
Miałem ten sam problem. Chcesz spojrzeć na obiekt połączenia dostarczony przez menedżera encji:
Następnie możesz zapytać / wykonać bezpośrednio przeciwko niemu:
Zobacz dokumentację obiektu połączenia pod adresem http://www.doctrine-project.org/api/dbal/2.0/doctrine/dbal/connection.html
źródło
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 ().
źródło
Nie możesz, Doctrine 2 nie zezwala na nieprzetworzone zapytania. Może się wydawać, że możesz, ale jeśli spróbujesz czegoś takiego:
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.
źródło