Thực thi SQL thô bằng Doctrine 2


102

Tôi muốn thực thi SQL thô bằng Doctrine 2

Tôi cần cắt bớt các bảng cơ sở dữ liệu và khởi tạo bảng với dữ liệu thử nghiệm mặc định.


2
Nhân tiện, khi tôi muốn thực hiện việc gruntwork cơ sở dữ liệu tự động, như thực hiện mysqldumphoặc tải dữ liệu từ các lần kết xuất trước đó hoặc giảm các bảng, tôi thường viết một tập lệnh shell cho công việc đó và sau đó viết một tác vụ (hoặc "lệnh", bằng ngôn ngữ Symfony2 ) thực thi tập lệnh shell. Mục đích của ORM, như tôi hiểu, là để loại bỏ những công việc lặp đi lặp lại và nếu bạn đang làm việc gì đó như cắt bớt một bảng, tôi không hiểu việc đưa Doctrine vào bức tranh sẽ có ý nghĩa như thế nào vì Doctrine không ' t làm cho nhiệm vụ đó dễ dàng hơn.
Jason Swett

Câu trả lời:


164

Đây là ví dụ về một truy vấn thô trong Doctrine 2 mà tôi đang thực hiện:

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
Câu trả lời rất hay. Để có được trình quản lý thực thể trong mã này, bạn có thể sử dụng $ this-> getDoctrine () -> getManager () thay cho mã này ở trên "$ this-> getEntityManager ()" , theo cách này nó đã hoạt động ngay với tôi.
webblover

hey của nó đem lại cho tôi Gọi phương pháp xác định chỉ số :: getDoctrine () những gì tôi nên làm gì
Dexter

im sử dụng codeigniter với học thuyết 2 wildlyinaccurate.com/integrating-doctrine-2-with-codeigniter-2
Dexter

1
Điều này đã dẫn tôi đi đúng hướng nhưng không chính xác là điều tôi cần. Tôi nghi ngờ rằng độ tuổi của câu trả lời tạo ra sự khác biệt. Tôi đã sử dụng: ...getConnection()->query($sql);và không phải chạy$stmt->execute();
Brandon

Lưu ý rằng với Symfony4 và autowiring, bạn có thể có thể gõ gợi ý EntityManagerInterface $entityManagervà sau đó gọi$entityManager->getConnection()
Coil

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

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

18
Ngoài ra, bạn nên gọi hàm chuẩn bị () thay vì thực thi để bạn vẫn có thể nhận được hỗ trợ câu lệnh chuẩn bị.
Jeremy Hicks

44

Tôi đã làm cho nó hoạt động bằng cách làm điều này, giả sử bạn đang sử dụng 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);

Bạn có thể thay đổi FETCH_TYPE để phù hợp với nhu cầu của mình.


1
Tốt nhất ví dụ trong số tất cả trong số họ
David

14

Cách thực hiện một Truy vấn thô và trả về dữ liệu.

Kết nối với người quản lý của bạn và tạo một kết nối mới:

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

Tạo truy vấn của bạn và tìm nạp Tất cả:

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

Lấy dữ liệu ra khỏi kết quả như thế này:

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

1
query () là khi SQL trả về một số dữ liệu bạn muốn sử dụng; exec () là khi nó không
Jeffiekins

12

Tôi phát hiện ra câu trả lời có lẽ là:

NativeQuery cho phép bạn thực thi SQL gốc, ánh xạ kết quả theo thông số kỹ thuật của bạn. Một đặc tả như vậy mô tả cách một tập kết quả SQL được ánh xạ tới một kết quả Doctrine được biểu diễn bằng một ResultSetMapping.

Nguồn: SQL gốc .


17
Đây là câu trả lời được chấp nhận nhưng tôi vẫn không thấy phần này của Doctrine hữu ích như thế nào vì bạn luôn cần ResultSetMapping. Tôi không muốn nó ánh xạ kết quả tới các Thực thể .... mặc định điểm chạy SQL tùy ý!
MikeMurko

2
@MikeMurko tôi tìm thấy bài này hữu ích cho việc chạy các truy vấn liệu trong Học thuyết 2: forum.symfony-project.org/viewtopic.php?f=23&t=37872
Jason Swett

Ngoài ra , SQL gốc không phải gốc sẽ không thực thi mọi truy vấn SQL có thể. DELETE / UPDATE / INSERT sẽ không hoạt động, cũng như một số định nghĩa bảng không tuân theo các giả định về học thuyết. (Bảng tham gia M2M không có id). Vì vậy, câu trả lời này không phải là phổ quát. Cũng không nên được chấp nhận là INSERT sẽ không hoạt động.
przemo_li

5

Tôi đã từng gặp vấn đề tương tự. Bạn muốn xem đối tượng kết nối do trình quản lý thực thể cung cấp:

$conn = $em->getConnection();

Sau đó, bạn có thể truy vấn / thực thi trực tiếp chống lại nó:

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

Xem tài liệu cho đối tượng kết nối tại http://www.doctrine-project.org/api/dbal/2.0/doctrine/dbal/connection.html


5

Trong mô hình của bạn, hãy tạo câu lệnh SQL thô (ví dụ dưới đây là ví dụ về khoảng ngày mà tôi phải sử dụng nhưng thay thế của riêng bạn. Nếu bạn đang thực hiện thêm SELECT -> fetchall () vào lệnh thực thi ().

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

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

    $stmt->execute();

4

Bạn không thể, Doctrine 2 không cho phép các truy vấn thô. Có vẻ như bạn có thể làm được nhưng nếu bạn thử một cái gì đó như thế này:

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

Doctrine sẽ đưa ra lỗi nói rằng DATE_FORMAT là một hàm không xác định.

Nhưng cơ sở dữ liệu của tôi (mysql) không biết chức năng đó, vì vậy về cơ bản điều gây khó khăn là Doctrine đang phân tích cú pháp truy vấn đó đằng sau hậu trường (và sau lưng bạn) và tìm ra một biểu thức mà nó không hiểu, coi truy vấn đó là không hợp lệ.

Vì vậy, nếu giống như tôi, bạn muốn có thể đơn giản gửi một chuỗi đến cơ sở dữ liệu và để nó xử lý (và để nhà phát triển chịu hoàn toàn trách nhiệm về bảo mật), hãy quên nó đi.

Tất nhiên bạn có thể viết mã một tiện ích mở rộng để cho phép điều đó theo cách này hay cách khác, nhưng bạn cũng nên sử dụng mysqli để làm điều đó và để Doctrine cho nó ORM buisness.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.