เรียกใช้ SQL ดิบโดยใช้หลักคำสอน 2


104

ฉันต้องการเรียกใช้ SQL ดิบโดยใช้หลักคำสอน 2

ฉันต้องการตัดทอนตารางฐานข้อมูลและเริ่มต้นตารางด้วยข้อมูลทดสอบเริ่มต้น


2
อย่างไรก็ตามเมื่อฉันต้องการทำฐานข้อมูลแบบอัตโนมัติเช่นทำmysqldumps หรือโหลดข้อมูลจากการทิ้งหรือวางตารางก่อนหน้านี้ฉันมักจะเขียนเชลล์สคริปต์สำหรับงานนั้นแล้วเขียนงาน (หรือ "คำสั่ง" ในภาษา Symfony2 ) ที่รันเชลล์สคริปต์ ตามที่ฉันเข้าใจจุดประสงค์ของ ORM คือการทำให้งานที่ซ้ำซากเป็นนามธรรมออกไปและถ้าคุณกำลังทำอะไรบางอย่างเช่นการตัดทอนตารางฉันไม่เห็นว่ามันจะสมเหตุสมผลอย่างไรที่จะนำหลักคำสอนเข้ามาในภาพเนื่องจาก Doctrine ไม่ ' ไม่ทำให้งานนั้นง่ายขึ้น
Jason Swett

คำตอบ:


166

นี่คือตัวอย่างแบบสอบถามดิบในหลักคำสอน 2 ที่ฉันกำลังทำ:

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
คำตอบที่ดี หากต้องการรับตัวจัดการเอนทิตีในรหัสนี้คุณสามารถใช้$ this-> getDoctrine () -> getManager ()แทนรหัสนี้ด้านบน"$ this-> getEntityManager ()"วิธีนี้ได้ผลสำหรับฉันทันที
webblover

เฮ้มันให้ฉันโทรหาวิธีที่ไม่ได้กำหนดดัชนี :: getDoctrine () ฉันควรทำอย่างไร
Dexter

ฉันใช้ Codeigniter กับหลักคำสอน 2 wildlyinaccurate.com/integrating-doctrine-2-with-codeigniter-2
Dexter

1
สิ่งนี้ทำให้ฉันไปในทิศทางที่ถูกต้อง แต่ไม่ใช่สิ่งที่ฉันต้องการ ฉันสงสัยว่าอายุของคำตอบนั้นสร้างความแตกต่าง ฉันใช้: ...getConnection()->query($sql);และไม่ต้องวิ่ง$stmt->execute();
Brandon

โปรดทราบว่าด้วย Symfony4 และการเดินสายอัตโนมัติคุณสามารถพิมพ์คำใบ้EntityManagerInterface $entityManagerแล้วโทร$entityManager->getConnection()
COil

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

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

20
นอกจากนี้ควรโทรหาการจัดเตรียม () แทนผู้บริหารเพื่อให้คุณยังคงได้รับการสนับสนุนงบ
Jeremy Hicks

45

ฉันทำให้มันทำงานได้โดยการทำเช่นนี้สมมติว่าคุณใช้ 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);

คุณสามารถเปลี่ยน FETCH_TYPE ให้เหมาะกับความต้องการของคุณ


1
ตัวอย่างที่ดีที่สุดจากทั้งหมด
เดวิด

14

วิธีดำเนินการแบบสอบถามดิบและส่งคืนข้อมูล

เชื่อมต่อกับผู้จัดการของคุณและทำการเชื่อมต่อใหม่:

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

สร้างแบบสอบถามของคุณและดึงข้อมูลทั้งหมด:

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

รับข้อมูลจากผลลัพธ์ดังนี้:

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

1
แบบสอบถาม () ใช้สำหรับเมื่อ SQL ส่งคืนข้อมูลบางอย่างที่คุณต้องการใช้ exec () มีไว้สำหรับเมื่อมันไม่ได้
Jeffiekins

12

ฉันพบว่าคำตอบน่าจะเป็น:

NativeQuery ช่วยให้คุณสามารถเรียกใช้ SQL แบบเนทีฟโดยทำแผนที่ผลลัพธ์ตามข้อกำหนดของคุณ ข้อกำหนดดังกล่าวที่อธิบายถึงวิธีการแมปชุดผลลัพธ์ SQL กับผลลัพธ์หลักคำสอนโดย ResultSetMapping

ที่มา: พื้นเมือง SQL


17
นี่เป็นคำตอบที่ได้รับการยอมรับ แต่ฉันยังไม่เห็นว่าส่วนนี้ของหลักคำสอนมีประโยชน์อย่างไรเพราะคุณต้องใช้ ResultSetMapping เสมอ ฉันไม่ต้องการให้แมปผลลัพธ์กับเอนทิตี .... ซึ่งเป็นค่าเริ่มต้นของการเรียกใช้ SQL โดยพลการ!
MikeMurko

2
@MikeMurko ฉันพบว่าโพสต์นี้มีประโยชน์สำหรับการเรียกใช้แบบสอบถามดิบในหลักคำสอน 2: forum.symfony-project.org/viewtopic.php?f=23&t=37872
Jason Swett

นอกจากนี้Non-native Native SQL จะไม่ดำเนินการค้นหา SQL ที่เป็นไปได้ทั้งหมด DELETE / UPDATE / INSERT จะไม่ทำงานหรือคำจำกัดความตารางบางส่วนที่ไม่เป็นไปตามสมมติฐานของหลักคำสอน (ตารางการเข้าร่วม M2M ที่ไม่มีรหัส) ดังนั้นคำตอบนี้จึงไม่เป็นสากล และไม่ควรยอมรับว่า INSERTs จะไม่ทำงาน
przemo_li

5

ผมมีปัญหาเหมือนกัน. คุณต้องการดูออบเจ็กต์การเชื่อมต่อที่จัดทำโดยผู้จัดการเอนทิตี:

$conn = $em->getConnection();

จากนั้นคุณสามารถสอบถาม / ดำเนินการโดยตรงกับมัน:

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

ดูเอกสารสำหรับวัตถุการเชื่อมต่อที่http://www.doctrine-project.org/api/dbal/2.0/doctrine/dbal/connection.html


5

ในโมเดลของคุณให้สร้างคำสั่ง SQL ดิบ (ตัวอย่างด้านล่างเป็นตัวอย่างของช่วงวันที่ที่ฉันต้องใช้ แต่แทนที่ของคุณเองหากคุณกำลังทำการ SELECT add -> fetchall () ไปยังการเรียก execute ()

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

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

    $stmt->execute();

4

คุณทำไม่ได้หลักคำสอน 2 ไม่อนุญาตให้มีการสืบค้นข้อมูลดิบ อาจดูเหมือนว่าคุณทำได้ แต่ถ้าคุณลองทำสิ่งนี้:

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

Doctrine จะพ่นข้อผิดพลาดที่บอกว่า DATE_FORMAT เป็นฟังก์ชันที่ไม่รู้จัก

แต่ฐานข้อมูลของฉัน (mysql) รู้จักฟังก์ชันนั้นดังนั้นโดยพื้นฐานแล้วสิ่งที่ทำให้เกิดความคาดหวังคือ Doctrine กำลังแยกวิเคราะห์แบบสอบถามนั้นเบื้องหลัง (และอยู่ด้านหลังของคุณ) และค้นหานิพจน์ที่ไม่เข้าใจโดยพิจารณาว่าแบบสอบถามไม่ถูกต้อง

ดังนั้นหากชอบฉันคุณต้องการเพียงแค่ส่งสตริงไปยังฐานข้อมูลและปล่อยให้มันจัดการกับมัน (และให้นักพัฒนารับผิดชอบต่อความปลอดภัยอย่างเต็มที่) ก็อย่าลืมไป

แน่นอนคุณสามารถเขียนโค้ดส่วนขยายเพื่อให้อนุญาตได้ไม่ทางใดก็ทางหนึ่ง แต่คุณก็สามารถใช้ mysqli ในการทำเช่นนั้นได้เช่นกันและออกจาก Doctrine ไปที่ ORM buisness

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.