Open nattapong99 opened 6 years ago
หนึ่งในสั่งที่พบมากที่สุดและเป็นงานท้าทายสำหรับแอพพลิเคชั่นใด ๆ ก็ตามจะเกี่ยวข้องกับการ persisting และอ่านข้อมูลจากฐานข้อมูล แม้ว่า Symfony Framework จะไม่ได้รวม component ที่ใช้ทำงานกับฐานข้อมูล แต่ก็มีการใช้ third-party library เรียกว่า Doctrine โดยเป้าหมายอย่างเดียวของ Doctrine คือการช่วยให้คุณมี เครื่องมือที่มีประสิทธิภาพในการทำงานกับฐานข้อมูล ทำงานได้ง่ายและยืดหยุ่นมากขึ้น
ในบทนี้เนื้อหาจะเกี่ยวกับ Doctrine ORM ซึ่งเป้าหมายคือการให้คุณสามารถแมฟ object ไปยัง relational database ได้ (เช่น MySQL, PostgreSQL หรือ Microsoft SQL)
วิธีที่ง่ายที่สุดในการทำความเข้าใจว่า Doctrine ทำงานยังไงคือการ ดูการทำงานของมัน ในหัวข้อนี้คุณจะได้ config ฐานข้อมูล, สร้าง Product object, persist ข้อมูลลงในฐานข้อมูลและนำข้อมูลมาแสดง
คุณต้องกำหนดค่าการเชื่อมต่อฐานข้อมูล โดยปกติไฟล์ที่ใช้ในการ config อยู่ที่ app/config/parameters.yml
app/config/parameters.yml
โดยปกติการกำหนดค่าทำผ่านไฟล์ parameters.yml โดยค่าที่กำหนดในไฟล์นี้จะถูกอ้างอิงไปยังไฟล์ config หลักเมื่อมีการตั้งค่า Doctrine
เมื่อแยกข้อมูลฐานข้อมูลลงในไฟล์ที่แยกจากกัน คุณสามารถเก็บไฟล์เวอร์ชันต่าง ๆ ไว้ในเซิร์ฟเวอร์แต่ละเครื่องได้อย่างง่ายดาย
เมื่อ Doctrine สามารถเชื่อมต่อกับฐานข้อมูลได้แล้ว คำสั่งข้างล่างนี้จะช่วยในการสร้างฐานข้อมูลเปล่าให้กับคุณ
การกำหนดค่าเริ่มต้น UTF8 สำหรับ MySQL ทำได้โดยเพิ่มการกำหนดค่าในไฟล์ (my.cnf)
นอกจากนี้คุณยังสามารถเปลี่ยนค่าเริ่มต้นสำหรับ Doctrine เพื่อให้ SQL ที่สร้างขึ้นใช้ชุดอักขระที่ถูกต้อง
สมมติว่าคุณกำลังสร้างแอปพลิเคชันที่ต้องแสดงผลิตภัณฑ์ ซึ่งคุณรู้อยู่แล้วว่าคุณต้องมี Product object เพื่อที่จะใช้แสดงถึงผลิตภัณฑ์เหล่านั้น ดังนั้น สร้างคลาสนี้ภายในไดเรกทอรีเอนทิตีของ AppBundle ของคุณ
class - มักเรียกว่า "entity" ซึ่งหมายถึงคลาสพื้นฐานที่เก็บข้อมูล - ซึ่งช่วยตอบสนองความต้องการทางธุรกิจของผลิตภัณฑ์ในแอ็พพลิเคชันของคุณ คลาสนี้ยังไม่สามารถ persist กับฐานข้อมูลได้
Doctrine ช่วยให้การทำงานกับฐานข้อมูลมีความน่าสนใจมากขึ้น จากแค่เรียกแถวของข้อมูลเป็นอาร์เรย์ แต่ Doctrine ทำให้คุณสามารถดึงข้อมูล object ทั้งหมดออกจากฐานข้อมูลและเก็บ object ทั้งหมดกลับลงไปในฐานข้อมูล เพื่อให้ Doctrine สามารถทำเช่นนี้ได้ คุณต้องแม็พตารางฐานข้อมูลของคุณกับคลาส PHP โดยคอลัมน์ในตารางเหล่านั้นต้องถูกแม็พกับ property ของคลาส PHP ให้ตรงกันด้วย
คุณจะต้องทำการแม็ฟข้อมูลเหล่านี้ในรูปแบบของ "metadata" ซึ่งชุดของกฎเหล่านี้จะบอก Doctrine ว่าควรกำหนดคลาส Product และ property ของมันให้ตรงกับตารางฐานข้อมูลที่ต้องการอย่างไร โดย metadata นี้สามารถระบุได้หลายรูปแบบเช่น YAML, XML หรือระบุโดยตรงภายในคลาส Product ผ่าน DocBlock adnotations
Product
โดย bundle หนึ่งสามารถระบุรูปแบบ metadata ได้แค่รูปแบบเดียว ไม่สามารถที่จะผสมรูปแบบ YMAL metadata กับ annotated PHP entity ได้ -------------------------- ชื่อของตารางหากไม่ได้กำหนด ชื่อจะถูกกำหนดโดยอัตโนมัติตามชื่อของคลาส entity
Doctrine มีตัวเลือก field types ที่หลากหลายให้เลือกใช้ โดยสามารถดู field types ที่สามารถใช้ได้ในหัวข้อ Doctrine Field Types Reference
โปรดระวังถ้าชื่อคลาสของเอนทิตี (หรือ property) ตรงกับคำสงวนของ SQL เช่น GROUP หรือ USER ตัวอย่าง เช่น ถ้าชื่อคลาสของเอนทิตีของคุณคือ Group โดยค่าเริ่มต้นชื่อตารางควรจะเป็น Group ซึ่งจะทำให้เกิดข้อผิดพลาด ของ SQL ในบาง engines ของฐานข้อมูล
Reserved SQL keywords documentation เป็นรายละเอียดเกี่ยวกับวิธีการหลีกเลี่ยงชื่อเหล่านี้อย่างเหมาะสม
ถึงแม้ว่าตอนนี้ Doctrine จะรู้วิธีการ persist Product object ไปยังฐานข้อมูล แต่คลาสเหล่านั้นยังไม่สามารถทำงานได้จริง ๆ เนื่องจาก Product เป็นเพียงคลาส PHP ปกติที่มี private property คุณต้องสร้างเมธอด getter และ setter แบบ public (เช่น getName(), setName($name)) เพื่อให้สามารถเข้าถึง property ในแอปพลิเคชันได้
private
public
getName()
setName($name)
ตอนนี้คุณมีคลาส Product ที่สามารถใช้งานได้แล้ว พร้อมข้อมูลการแม็ฟที่ทำไว้ ซึ่งทำให้ Doctrine รู้ว่าจะ persist อย่างไร แต่ ณ ตอนนี้คุณยังไม่มีตาราง product ในฐานข้อมูล ซึ่ง Doctrine สามารถสร้างตารางฐานข้อมูลทั้งหมดที่จำเป็นสำหรับเอนทิตีทั้งหมดในแอปพลิเคชันของคุณได้ โดยใช้คำสั่ง
ถ้ามีการเพิ่ม property ใหม่ให้กับคลาส product และทำการแม็ฟเรียบร้อยแล้ว การเรียกใช้คำสั่งนี้ มันจะทำการ เรียกใช้คำสั่ง "ALTER TABLE" เพื่อสร้างคอลัมน์ใหม่เพิ่มในตาราง product ให้ วิธีที่ดีในการใช้ประโยชน์จากฟังก์ชันนี้ก็คือใช้ผ่าน migrations ซึ่งช่วยให้คุณสามารถสร้างคำสั่ง SQL เหล่านี้ และจัดเก็บไว้ใน migration class นั้นสามารถทำให้การเรียกใช้คำสั่งเป็นระบบมากขึ้นบน production เซิร์ฟเวอร์ เนื่องจากการเราสามารถอัพเดท ติดตามการเปลี่ยนแปลงของฐานข้อมูลได้ ซึ่งทำให้ฐานข้อมูลมีความ ปลอดภัยและน่าเชื่อถือ ไม่ว่าอย่างไรก็ตาม การใช้คำสั่ง doctrine:schema:update ควรใช้ในระหว่างพัฒนาเท่านั้น ไม่ควรใช้บน production environment
เมื่อแม็ฟ Product entity ตรงกับตาราง product เรียบร้อยแล้ว ทำให้ตอนนี้คุณสามารถ persist Product object ลงในฐานข้อมูลได้แล้ว ด้วยการเพิ่มเมธอดเหล่านี้ลงใน DefaltController ดังตัวอย่าง
DefaltController
รายละเอียดเพิ่มเติมของโค้ดข้างบน
$this->getDoctrine()->getManager()
persist($product)
$product
flush()
INSERT
product
การดึง object จากฐานข้อมูลเป็นเรื่องง่ายมาก จากตัวอย่าง สมมติคุณกำหนด route ที่จะแสดง Product โดยอ้างอิงจากค่า id ของมัน
id
เมื่อคุณค้นหารายละเอียดต่าง ๆ ของ object คุณควรใช้สิ่งที่เรียกว่า "reposity" เสมอ โดย repository เป็นคลาส PHP ที่มีหน้าที่เกี่ยวกับการเรียกข้อมูลเอนทิตี้ของคลาสโดยเฉพาะ คุณสามารถเข้าถึง repository object สำหรับคลาสเอนทิตีได้ผ่านทาง
คุณสามารถใช้ syntax AppBundle:Product ซึ่งเป็นคีย์ลัดที่สามารถใช้ได้ทุกที่ใน Doctrine แทนการใช้ชื่อเต็ม ของคลาสของเอนทิตี (เช่น AppBundle\Entity\Product) ตราบใดก็ตามที่เอนทิตีของคุณอยู่ภายใต้ Entity namespace ของ bundle มันจะทำงานได้
เมื่อคุณมี repository object คุณจะสามารถเข้าถึงทุกเมธอดที่มีประโยชน์ ได้ดังตัวอย่าง
โดยคุณสามารถนำข้อดีของเมธอด findBy() และ findOneBy มาใช้เพื่อดึง object บนเงื่อนไขที่มากขึ้นได้ เช่น
findBy()
findOneBy
เมื่อคุณดึง object มาจากฐานข้อมูลได้แล้ว การอัพเดทก็เป็นเรื่องง่ายเช่นกัน สมมติคุณมี route ที่ใช้ product id เพื่ออัพเดทใน controller ดังตัวอย่าง
การอัพเดท object มีสามขั้นตอน
ไม่จำเป็นต้องใช้คำสั่ง $em->persist($product) โดยทั่วไปเมธอดนี้จะเป็นตัวบอก Doctrine เพื่อให้ manage หรือ "watch" $product object แต่ในกรณีนี้ เมื่อคุณดึง $product object มาจาก Doctrine มันจะรู้อยู่แล้วว่าต้อง managed
$em->persist($product)
การลบ object ทำได้โดยใช้เมธอด remove() ของ entity manager
remove()
คุณอาจคาดไว้ว่าเมธอด remove() จะแจ้ง Doctrine ว่าคุณต้องการลบ object ออกจากฐานข้อมูล แต่การลบจริง ๆ จะเกิดขึ้นเมื่อคุณเรียกใช้เมธอด flush()
คุณได้เห็นแล้วว่า repository object ช่วยให้คุณ run basic query ได้อย่างไร
ที่นี้ Doctrine จะช่วยให้คุณสามารถเขียน query ที่ซับซ้อนมากขึ้นได้โดยใช้ Doctinre Query Language (DQL) ซึ่ง DQL มีความคล้ายกับ SQL เว้นแต่ว่าคุณควรจินตนาการว่าคุณกำลัง query object ของคลาสเอนทิตี มาหนึ่ง object หรือมากกว่านั้น (เช่น Product) แทนที่การ query แถวของตาราง (เช่น product)
ซึ่งการ query ของ Doctrine มีสองวิธีหลักคือ เขียน pure DQL query หรือใช้ Query Builder ของ Doctrine
สมมติคุณต้องการดึงข้อมูลสินค้าที่มีต้นทุนมากกว่า 19.99 และเรียงลำดับค่าจากน้อยไปมาก คุณสามารถใช้ DQL ได้ดังตัวอย่าง
ถ้าคุณรู้สึกพอใจกับการใช้ SQL แล้ว DQL ก็จะเป็นเรื่องธรรมดา ๆ แต่สิ่งที่แตกต่างมากที่สุดคือคุณต้องนึกถึงเงื่อนไขของการ selecting PHP object แทนที่การดึงแถวข้อมูลในฐานข้อมูล ด้วยเหตุนี้คุณจึง select from AppBundle:Product entity และตั้งคีย์ลัดเป็น p
AppBundle:Product
p
เมธอด setParameter() จะทำงานเมื่อใช้กับ Doctrine มันเป็นความคิดที่ดีในการกำหนดค่าไว้ข้างนอกซึ่งเรียก ว่า "placeholders" (จากตัวอย่างข้างบนคือ :price) เพื่อเป็นการป้องกัน SQL injection attacks
เมธอด getResult() จะส่งผลลัพธ์กลับมาเป็น array หากต้องการผลลัพธ์แค่หนึ่งสามารถใช้เมธอด getOneOrNullResult()
getResult()
getOneOrNullResult()
DQL syntax มีประสิทธิภาพมาก ซึ่งช่วยให้การ join กันระหว่างเอนทิตีเป็นเรื่องง่าย ดูรายละเอียดที่หัวข้อ relations
แทนที่จะเขียนแบบ DQL string ดังตัวอย่างก่อนหน้า คุณสามารถเรียกใช้ object ที่ชื่อว่า QueryBuilder เพื่อสร้าง string ให้คุณ สิ่งนี้จะเป็นประโยชน์เมื่อการ query ขึ้นอยู่กับเงื่อนไขแบบ dynamic ซึ่งจะทำให้โค้ดของคุณเริ่มอ่านยากขึ้นหากเขียนแบบ DQL string ลองดูตัวอย่างนี้
QueryBuilder object จะบรรจุทุกเมธอดที่จำเป็นในการสร้าง query การเรียกใช้เมธอด getQuery() ทำให้ query builder ส่ง Query object ธรรมดากลับมา ซึ่งทำให้สามารถเข้าถึงผลลัพธ์ของการ query ได้
QueryBuilder
getQuery()
Query
สำหรับข้อมูลเพิ่มเติม Query Builder ของ Doctrine ดุได้ที่ Query Builder
จาก query ทั้งหมดในหัวข้อก่อนหน้านี้ได้เขียนลงใน controller โดยตรง แต่เพื่อความเป็นระเบียบ Doctrine มีสามารถสร้าง special repository class ที่ช่วยให้คุณเก็บ query ทั้งหมดไว้ในที่เดียว ดูเพิ่มเติมได้ที่ How to Create custom Repository Classes
Doctrine มีค่าที่กำหนดได้เองมาก แต่คุณอาจไม่จำเป็นต้องกังวลเกี่ยวกับ option นี้มากนัก หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดค่า Doctrine โปรดดูที่หัวข้อ config refernce
ด้วย Doctrine คุณสามารถมุ่งเน้นไปที่ object ของคุณและการใช้พวกมันในแอปพลิเคชั่น จากนั้นค่อยนึกถึงเรื่อง persistence ฐานข้อมูล เนื่องจาก Doctrine ช่วยให้คุณใช้ PHP object เพื่อเก็บข้อมูลและการทำแม็ฟ metadata เพื่อแม็ฟ object data กับตารางฐานข้อมูล
Doctrine มีความสามารถอีกมากให้เรียนรู้ ได้แก่ relationships, complex queries, event listeners
source
Databases and the Doctrine ORM
หนึ่งในสั่งที่พบมากที่สุดและเป็นงานท้าทายสำหรับแอพพลิเคชั่นใด ๆ ก็ตามจะเกี่ยวข้องกับการ persisting และอ่านข้อมูลจากฐานข้อมูล แม้ว่า Symfony Framework จะไม่ได้รวม component ที่ใช้ทำงานกับฐานข้อมูล แต่ก็มีการใช้ third-party library เรียกว่า Doctrine โดยเป้าหมายอย่างเดียวของ Doctrine คือการช่วยให้คุณมี เครื่องมือที่มีประสิทธิภาพในการทำงานกับฐานข้อมูล ทำงานได้ง่ายและยืดหยุ่นมากขึ้น
A Simple Example: A Product
วิธีที่ง่ายที่สุดในการทำความเข้าใจว่า Doctrine ทำงานยังไงคือการ ดูการทำงานของมัน ในหัวข้อนี้คุณจะได้ config ฐานข้อมูล, สร้าง Product object, persist ข้อมูลลงในฐานข้อมูลและนำข้อมูลมาแสดง
Configuring the Database
คุณต้องกำหนดค่าการเชื่อมต่อฐานข้อมูล โดยปกติไฟล์ที่ใช้ในการ config อยู่ที่
app/config/parameters.yml
โดยปกติการกำหนดค่าทำผ่านไฟล์ parameters.yml โดยค่าที่กำหนดในไฟล์นี้จะถูกอ้างอิงไปยังไฟล์ config หลักเมื่อมีการตั้งค่า Doctrine
เมื่อแยกข้อมูลฐานข้อมูลลงในไฟล์ที่แยกจากกัน คุณสามารถเก็บไฟล์เวอร์ชันต่าง ๆ ไว้ในเซิร์ฟเวอร์แต่ละเครื่องได้อย่างง่ายดาย
เมื่อ Doctrine สามารถเชื่อมต่อกับฐานข้อมูลได้แล้ว คำสั่งข้างล่างนี้จะช่วยในการสร้างฐานข้อมูลเปล่าให้กับคุณ
Setting up the Database to be UTF8
การกำหนดค่าเริ่มต้น UTF8 สำหรับ MySQL ทำได้โดยเพิ่มการกำหนดค่าในไฟล์ (my.cnf)
นอกจากนี้คุณยังสามารถเปลี่ยนค่าเริ่มต้นสำหรับ Doctrine เพื่อให้ SQL ที่สร้างขึ้นใช้ชุดอักขระที่ถูกต้อง
Creating an Entity Class
สมมติว่าคุณกำลังสร้างแอปพลิเคชันที่ต้องแสดงผลิตภัณฑ์ ซึ่งคุณรู้อยู่แล้วว่าคุณต้องมี Product object เพื่อที่จะใช้แสดงถึงผลิตภัณฑ์เหล่านั้น ดังนั้น สร้างคลาสนี้ภายในไดเรกทอรีเอนทิตีของ AppBundle ของคุณ
class - มักเรียกว่า "entity" ซึ่งหมายถึงคลาสพื้นฐานที่เก็บข้อมูล - ซึ่งช่วยตอบสนองความต้องการทางธุรกิจของผลิตภัณฑ์ในแอ็พพลิเคชันของคุณ คลาสนี้ยังไม่สามารถ persist กับฐานข้อมูลได้
Add Mapping Information
Doctrine ช่วยให้การทำงานกับฐานข้อมูลมีความน่าสนใจมากขึ้น จากแค่เรียกแถวของข้อมูลเป็นอาร์เรย์ แต่ Doctrine ทำให้คุณสามารถดึงข้อมูล object ทั้งหมดออกจากฐานข้อมูลและเก็บ object ทั้งหมดกลับลงไปในฐานข้อมูล เพื่อให้ Doctrine สามารถทำเช่นนี้ได้ คุณต้องแม็พตารางฐานข้อมูลของคุณกับคลาส PHP โดยคอลัมน์ในตารางเหล่านั้นต้องถูกแม็พกับ property ของคลาส PHP ให้ตรงกันด้วย
คุณจะต้องทำการแม็ฟข้อมูลเหล่านี้ในรูปแบบของ "metadata" ซึ่งชุดของกฎเหล่านี้จะบอก Doctrine ว่าควรกำหนดคลาส
Product
และ property ของมันให้ตรงกับตารางฐานข้อมูลที่ต้องการอย่างไร โดย metadata นี้สามารถระบุได้หลายรูปแบบเช่น YAML, XML หรือระบุโดยตรงภายในคลาส Product ผ่าน DocBlock adnotationsDoctrine มีตัวเลือก field types ที่หลากหลายให้เลือกใช้ โดยสามารถดู field types ที่สามารถใช้ได้ในหัวข้อ Doctrine Field Types Reference
Reserved SQL keywords documentation เป็นรายละเอียดเกี่ยวกับวิธีการหลีกเลี่ยงชื่อเหล่านี้อย่างเหมาะสม
Generating Getters and Setters
ถึงแม้ว่าตอนนี้ Doctrine จะรู้วิธีการ persist Product object ไปยังฐานข้อมูล แต่คลาสเหล่านั้นยังไม่สามารถทำงานได้จริง ๆ เนื่องจาก Product เป็นเพียงคลาส PHP ปกติที่มี
private
property คุณต้องสร้างเมธอด getter และ setter แบบpublic
(เช่นgetName()
,setName($name)
) เพื่อให้สามารถเข้าถึง property ในแอปพลิเคชันได้Creating the Database Tables/Schema
ตอนนี้คุณมีคลาส Product ที่สามารถใช้งานได้แล้ว พร้อมข้อมูลการแม็ฟที่ทำไว้ ซึ่งทำให้ Doctrine รู้ว่าจะ persist อย่างไร แต่ ณ ตอนนี้คุณยังไม่มีตาราง product ในฐานข้อมูล ซึ่ง Doctrine สามารถสร้างตารางฐานข้อมูลทั้งหมดที่จำเป็นสำหรับเอนทิตีทั้งหมดในแอปพลิเคชันของคุณได้ โดยใช้คำสั่ง
Persisting Objects to the Database
เมื่อแม็ฟ Product entity ตรงกับตาราง product เรียบร้อยแล้ว ทำให้ตอนนี้คุณสามารถ persist
Product
object ลงในฐานข้อมูลได้แล้ว ด้วยการเพิ่มเมธอดเหล่านี้ลงในDefaltController
ดังตัวอย่างรายละเอียดเพิ่มเติมของโค้ดข้างบน
$this->getDoctrine()->getManager()
เป็นการดึง entity manager object ของ Doctrine ซึ่งเป็น object ที่สำคัญที่สุดใน Doctrine โดยความรับผิดชอบของมันคือการบันทึก object ลงฐานข้อมูล, ดึง object จากฐานข้อมูลมาแสดงpersist($product)
คำสั่งนี้เป็นการบอก Doctrine ให้ "จัดการ"$product
object ซึ่งตอนนี้ยังไม่ได้ทำการ query ไปยังฐานข้อมูลflush()
Doctrine จะมองวัตถุทั้งหมดที่ต้องจัดการเพื่อดูว่าจำเป็นต้องมีการ persist กับฐานข้อมูลหรือไม่ จากตัวอย่าง$product
object ยังไม่มีอยู่ในฐานข้อมูล ดังนั้น entity manager จะใช้คำสั่งINSERT
สร้างแถวใหม่ในตารางproduct
Fetching Objects from the Database
การดึง object จากฐานข้อมูลเป็นเรื่องง่ายมาก จากตัวอย่าง สมมติคุณกำหนด route ที่จะแสดง
Product
โดยอ้างอิงจากค่าid
ของมันเมื่อคุณค้นหารายละเอียดต่าง ๆ ของ object คุณควรใช้สิ่งที่เรียกว่า "reposity" เสมอ โดย repository เป็นคลาส PHP ที่มีหน้าที่เกี่ยวกับการเรียกข้อมูลเอนทิตี้ของคลาสโดยเฉพาะ คุณสามารถเข้าถึง repository object สำหรับคลาสเอนทิตีได้ผ่านทาง
เมื่อคุณมี repository object คุณจะสามารถเข้าถึงทุกเมธอดที่มีประโยชน์ ได้ดังตัวอย่าง
โดยคุณสามารถนำข้อดีของเมธอด
findBy()
และfindOneBy
มาใช้เพื่อดึง object บนเงื่อนไขที่มากขึ้นได้ เช่นUpdating an Object
เมื่อคุณดึง object มาจากฐานข้อมูลได้แล้ว การอัพเดทก็เป็นเรื่องง่ายเช่นกัน สมมติคุณมี route ที่ใช้ product id เพื่ออัพเดทใน controller ดังตัวอย่าง
การอัพเดท object มีสามขั้นตอน
flush()
ของ entity managerไม่จำเป็นต้องใช้คำสั่ง
$em->persist($product)
โดยทั่วไปเมธอดนี้จะเป็นตัวบอก Doctrine เพื่อให้ manage หรือ "watch"$product
object แต่ในกรณีนี้ เมื่อคุณดึง$product
object มาจาก Doctrine มันจะรู้อยู่แล้วว่าต้อง managedDeleting an Object
การลบ object ทำได้โดยใช้เมธอด
remove()
ของ entity managerคุณอาจคาดไว้ว่าเมธอด
remove()
จะแจ้ง Doctrine ว่าคุณต้องการลบ object ออกจากฐานข้อมูล แต่การลบจริง ๆ จะเกิดขึ้นเมื่อคุณเรียกใช้เมธอดflush()
Querying for Objects
คุณได้เห็นแล้วว่า repository object ช่วยให้คุณ run basic query ได้อย่างไร
ที่นี้ Doctrine จะช่วยให้คุณสามารถเขียน query ที่ซับซ้อนมากขึ้นได้โดยใช้ Doctinre Query Language (DQL) ซึ่ง DQL มีความคล้ายกับ SQL เว้นแต่ว่าคุณควรจินตนาการว่าคุณกำลัง query object ของคลาสเอนทิตี มาหนึ่ง object หรือมากกว่านั้น (เช่น
Product
) แทนที่การ query แถวของตาราง (เช่นproduct
)ซึ่งการ query ของ Doctrine มีสองวิธีหลักคือ เขียน pure DQL query หรือใช้ Query Builder ของ Doctrine
Querying for Objects with DQL
สมมติคุณต้องการดึงข้อมูลสินค้าที่มีต้นทุนมากกว่า 19.99 และเรียงลำดับค่าจากน้อยไปมาก คุณสามารถใช้ DQL ได้ดังตัวอย่าง
ถ้าคุณรู้สึกพอใจกับการใช้ SQL แล้ว DQL ก็จะเป็นเรื่องธรรมดา ๆ แต่สิ่งที่แตกต่างมากที่สุดคือคุณต้องนึกถึงเงื่อนไขของการ selecting PHP object แทนที่การดึงแถวข้อมูลในฐานข้อมูล ด้วยเหตุนี้คุณจึง select from
AppBundle:Product
entity และตั้งคีย์ลัดเป็นp
เมธอด
getResult()
จะส่งผลลัพธ์กลับมาเป็น array หากต้องการผลลัพธ์แค่หนึ่งสามารถใช้เมธอดgetOneOrNullResult()
DQL syntax มีประสิทธิภาพมาก ซึ่งช่วยให้การ join กันระหว่างเอนทิตีเป็นเรื่องง่าย ดูรายละเอียดที่หัวข้อ relations
Querying for Objects Using Doctrine's Query Builder
แทนที่จะเขียนแบบ DQL string ดังตัวอย่างก่อนหน้า คุณสามารถเรียกใช้ object ที่ชื่อว่า QueryBuilder เพื่อสร้าง string ให้คุณ สิ่งนี้จะเป็นประโยชน์เมื่อการ query ขึ้นอยู่กับเงื่อนไขแบบ dynamic ซึ่งจะทำให้โค้ดของคุณเริ่มอ่านยากขึ้นหากเขียนแบบ DQL string ลองดูตัวอย่างนี้
QueryBuilder
object จะบรรจุทุกเมธอดที่จำเป็นในการสร้าง query การเรียกใช้เมธอดgetQuery()
ทำให้ query builder ส่งQuery
object ธรรมดากลับมา ซึ่งทำให้สามารถเข้าถึงผลลัพธ์ของการ query ได้สำหรับข้อมูลเพิ่มเติม Query Builder ของ Doctrine ดุได้ที่ Query Builder
Organizing Custom Queries into Repository Classes
จาก query ทั้งหมดในหัวข้อก่อนหน้านี้ได้เขียนลงใน controller โดยตรง แต่เพื่อความเป็นระเบียบ Doctrine มีสามารถสร้าง special repository class ที่ช่วยให้คุณเก็บ query ทั้งหมดไว้ในที่เดียว ดูเพิ่มเติมได้ที่ How to Create custom Repository Classes
Configuration
Doctrine มีค่าที่กำหนดได้เองมาก แต่คุณอาจไม่จำเป็นต้องกังวลเกี่ยวกับ option นี้มากนัก หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดค่า Doctrine โปรดดูที่หัวข้อ config refernce
Final Thoughts
ด้วย Doctrine คุณสามารถมุ่งเน้นไปที่ object ของคุณและการใช้พวกมันในแอปพลิเคชั่น จากนั้นค่อยนึกถึงเรื่อง persistence ฐานข้อมูล เนื่องจาก Doctrine ช่วยให้คุณใช้ PHP object เพื่อเก็บข้อมูลและการทำแม็ฟ metadata เพื่อแม็ฟ object data กับตารางฐานข้อมูล
Doctrine มีความสามารถอีกมากให้เรียนรู้ ได้แก่ relationships, complex queries, event listeners
source