เริ่มต้นอย่างรวดเร็ว) ฉีด Symfony (DI Dependency Tutorial
คืออะไร Dependency Injection (DI)?
ฉีด Dependency เป็นเทคนิคที่ช่วยให้การประกอบวัตถุอย่างอิสระภายในโปรแกรมซอฟต์แวร์ โดยทั่วไปถ้าวัตถุต้องเข้าถึงฟังก์ชันการทำงานของผู้อื่นมันจะ instantiated ภายในที่นำไปสู่ระบบการประกอบแน่น โดยการใช้การฉีดขึ้นต่อเราฉีดวัตถุต้องพร้อมใช้งาน (บางครั้งยังเรียกการผกผันของการควบคุม -- IOC) ใช้ตัวอย่างต่อไปนี้
<? PHP ชั้น DecisionMaker { makeDecision ทำงานสาธารณะ (array พารามิเตอร์ $) { / / ต้องการอะแดปเตอร์ฐานข้อมูล DP = $ DecisionParameters ใหม่ (); $ parameterScore = getScore $ DP -> ($ ตัวแปร); * / ... ตรรกะในการตัดสินใจบางรายละเอียดเพิ่มเติม ... * / กลับมา ($ parameterScore> 50); } }
ชิ้นส่วนของรหัสนี้จะมีการบอกกับคู่ให้แน่นเพื่อ DecisionParameters วัตถุ เขียนข้างต้นในแฟชั่นคู่อย่างอิสระเราจะได้สิ่งที่ต้องการ ...
<? PHP ชั้น DecisionMaker { ส่วนตัว $ _dp; ทำงานสาธารณะ __construct ($ DP) { $ this -> _dp = $ DP; } makeDecision ทำงานสาธารณะ (array พารามิเตอร์ $) { $ parameterScore = _dp -> $ this -> getScore ($ ตัวแปร); * / ... ตรรกะในการตัดสินใจบางรายละเอียดเพิ่มเติม ... * / กลับมา ($ parameterScore> 50); } }
ขณะที่ดึงดูดประโยชน์ของรหัสคู่อย่างอิสระเราจะเพิ่มความซับซ้อนดังกล่าวว่าทุกครั้งที่วัตถุเป็น instantiated เรายังมีการยกตัวอย่างการอ้างอิงและผ่านเหล่านี้ในเกินไป ตัวอย่างเช่นนี้
ทางเลือกใหม่ = $ DecisionMaker (); makeDecision echo $ ตัวเลือก -> (array ('ความพยายาม'=>'กลับ''ต่ำ'=>'สูง'));
ขณะนี้เป็น :
DP = $ DecisionParameters ใหม่ (); $ = ทางเลือกใหม่ DecisionMaker ($ DP); makeDecision echo $ ตัวเลือก -> (array ('ความพยายาม'=>'กลับ''ต่ำ'=>'สูง'));
สถานการณ์เช่นนี้จะกลายเป็นความเจ็บปวดมากขึ้นเป็นตัวเลขของการอ้างอิงสำหรับชั้นเรียนเพิ่มขึ้นและสิ่งที่ถ้ามีการอ้างอิงตัวเอง dependencies? ได้อย่างรวดเร็วนี้ค่อนข้างจะเป็นฝันร้ายของการบริหารวัตถุ! ใส่ภาชนะบรรจุที่พึ่งพาการฉีด (หรือกรอบ) ...
Dependency ภาชนะบรรจุยาฉีด / กรอบแนวทาง
Dependency ภาชนะบรรจุยาฉีด (หรือกรอบ) มือจับขั้นตอนของการวัตถุ; instantiating และฉีดอ้างอิงใด ๆ ก่อนที่จะกลับไปยังผู้โทรอินสแตนซ์
ในรหัสของคุณแทนที่จะสร้างวัตถุใหม่โดยตรงและได้ขอให้สำเนาของวัตถุจากภาชนะ DI วัตถุที่เราจะถูกส่งคืนแล้วมีการอ้างอิงทั้งหมดของมันฉีดและวัตถุนั้นสามารถพร้อมที่จะไป
Symfony คอนเทนเนอร์ Dependency Injection
Symfony น่าจะรู้จักกันดีที่สุดสำหรับเต็มของพวกเขา stack MVC กรอบการทำงาน แต่พวกเขาได้ออกยังเป็นอิสระจำนวนของชิ้นส่วนที่สามารถใช้ ตัวอย่างเช่นการพึ่งพาการฉีดภาชนะที่เรากำลังจะพูดคุยเกี่ยวกับที่นี่, YAML parser, เครื่องยนต์ templating ให้ดู ชิ้นส่วน Symfony สำหรับข้อมูลเพิ่มเติม
DI ภาชนะ Symfony จะขึ้นอยู่กับว่าจาก Spring Framework ใน Java .
Bootstrapping
เพื่อที่จะ bootstrap กรอบ Symfony พึ่งพาการฉีดเราจะใช้รหัสเป็นรวมอยู่ด้านล่าง ฉันได้เลือกที่จะใช้ YAML เพียงเพราะง่ายต่อการอ่านและการตั้งค่าของ สำหรับความเร็วสูงสุดที่คุณอาจต้องการที่จะเขียนออกภาชนะบรรจุของคุณจะธรรมดา PHP (ภาชนะ Symfony สามารถทำเพื่อคุณเมื่อการติดตั้ง) หรืออีกทางเลือกหนึ่งแคชใช้ภาชนะทั้งหมด Zend_Cache หรือที่คล้ายกัน
หากต้องการติดตั้ง Symfony DI ทำตามคำแนะนำในที่นี้ http://components.symfony-project.org/dependency-injection/installation , และเพิ่มในเส้นทางของคุณ
/ / โหลดภาชนะ Symfony DI ต้อง'sfServiceContainerBuilder.php'; ภาชนะ = $ sfServiceContainerBuilder ใหม่ (); $ loader = sfServiceContainerLoaderFileYaml ใหม่ ($ ภาชนะ); โหลด $ loader -> (APPLICATION_PATH'/ config / di / services.yml'.)
ประการแรกที่เรายกตัวอย่างภาชนะใหม่แล้วเราโหลดการตั้งค่าของเราจากไฟล์ YAML หมายเหตุ : ภาชนะ DI สามารถโหลด config จากหลายรูปแบบเช่น XML , YAML, PHP, และ INI *. ฉันมักจะรวมไฟล์ YAML เดียวและไฟล์อื่น ๆ นำเข้าจากภายในมี
กำหนดค่าไฟล์จำนวนมากสามารถนำเข้าโดยใช้รูปแบบที่แตกต่างกันความหมายที่เขียนทับใหม่ที่ยังไม่ได้กำหนดไว้ แฟ้มการกำหนดค่าอาจรวมถึงการอ้างอิงถึงวัตถุและพารามิเตอร์
* INI เพียงสามารถกำหนดค่าพารามิเตอร์และไม่สามารถนำเข้าไฟล์อื่น ๆ
ตัวอย่างการกำหนดค่า
นำเข้า : -- {ทรัพยากร : daos.yml} พารามิเตอร์ : ชื่อผู้ใช้ : เท็จ บริการ : # รูปแบบของลูกค้า model.customer : ชั้น : Pro_Customer โทร : -- [setLogger, [utils.logger] @] -- [setDao, [@ data.userdata.mysql]] -- [setUserName,% ชื่อผู้ใช้ [%]] # รูปแบบสินค้า model.product : ชั้น : Pro_Product อาร์กิวเมนต์ : [%% ชื่อผู้ใช้, {type :%% accesslevel, lastlogin :% lastlogin%}] โทร : -- [setDao, [@ data.product.mysql]] # คนตัดไม้ utils.logger : ชั้น : Pro_Logger สร้าง : getInstance โทร : -- [setHandle, [utils.filewriter] @]
ฉันคิดว่าโค้ดด้านบนเป็นธรรมคำอธิบายตนเอง แต่เพื่อความชัดเจนฉันจะอธิบายแต่ละส่วนในขณะนี้
ก่อนปิดเรากำหนดการนำเข้าบางส่วน (เช่นไฟล์อื่น ๆ เพื่อแยกวิเคราะห์) ผมชอบไปยังกลุ่มการกำหนดค่าของฉันสำหรับ DAOs ตัวอย่างในไฟล์เดียวสาธารณูปโภคในอื่นและชื่อไฟล์ได้อย่างเหมาะสม ขณะที่ช้าลงจะเพิ่มความเร็วในการบำรุงรักษาของการกำหนดค่าไฟล์ อาจเป็นไปได้ในการแยกไฟล์รูปแบบอื่น ๆ โดยใช้แฟล็กนำเข้าที่แตกต่างกัน แฟ้มจะถูกแยกวิเคราะห์ในลำดับที่มีข้อกำหนดใหม่เขียนทับหรือแก้ไขเพิ่มเติมที่กำหนดไว้ก่อนหน้านี้บริการ / พารามิเตอร์
ต่อไปเรากำหนดพารามิเตอร์, พารามิเตอร์ที่อาจจะมีชนิดตัวแปร PHP ณ จุดนี้ผมไม่ทราบว่าพารามิเตอร์ชื่อผู้ใช้ของฉันควรจะ (ฉันจำเป็นต้องตรวจสอบให้ว่า!) ดังนั้นฉันได้กำหนดค่าเริ่มต้นและฉันจะเขียนทับค่าที่ภายหลัง ชั้นเรียนหมายเหตุยังไม่ได้ instantiated จนกว่าคุณจะถามพวกเขาเพื่อกำหนดพารามิเตอร์เพียงเล็กน้อยต่อมาเป็นเรื่องปกติอย่างสมบูรณ์แบบ ต่อไปนี้ผมกำหนดให้บริการบางอย่าง
- ยกตัวอย่าง Pro_Customer ผ่านตัวอย่างเช่นคนตัดไม้ของฉันของฉัน setLogger () วิธีการเพิ่มใน MySQL การเข้าถึงข้อมูลวัตถุ (DAO), และส่งผ่านชื่อผู้ใช้เช่นกัน ทุกครั้งที่ผมถามสำหรับวัตถุนี้แต่ละฉันต้องการตัวอย่างใหม่
- สร้างอินสแตนซ์ของ Pro_Product ผ่านอาร์กิวเมนต์ของอาร์เรย์ชื่อผู้ใช้และตัวเลือกในการจัดสร้าง หลังจาก setDao โทร instantiation () และส่งผ่านสินค้าไอทีของฉัน DAO
- ให้ฉันสำเนาของ Pro_Logger, ยกตัวอย่างโดยใช้ getInstance () วิธีการและส่งสำเนาของวัตถุนักเขียนของฉันไฟล์ผ่าน setHandle () ครั้งที่โหลด นักเขียนไฟล์ของฉันถูกกำหนดไว้ในหนึ่งของการนำเข้าของฉัน
ภายในกำหนดค่าบริการไฟล์ที่อ้างอิงจาก prepending ชื่อกับ @'สัญลักษณ์', พารามิเตอร์อ้างอิงโดย prepending และต่อท้ายด้วย'%'สัญลักษณ์ eg@utils.logger%% ชื่อผู้ใช้
โพสต์ข้อมูลการเพิ่มโหลด
บางครั้งคุณอาจไม่ทราบว่าค่าพารามิเตอร์ของควรจะจนกว่าคุณจะมี bootstrapped เช่นเดียวกับพารามิเตอร์ชื่อผู้ใช้ของเราด้านบน เพื่อที่จะเขียนทับค่า offsetSet () วิธีใช้ขั้นแรกผ่านชื่อตัวแปรตามด้วยค่าใหม่ของมัน
offsetSet $ ภาชนะ -> ('ชื่อผู้ใช้', $ ชื่อผู้ใช้); เริ่มจากภาชนะบรรจุวัตถุ
การตั้งค่าเมื่อมากกว่า instantiating วัตถุโดยตรงตอนนี้เราไปที่ตู้ DI ที่จะได้รับอินสแตนซ์ ด้วย Symfony DI เราเรียก getService () วิธีการผ่านในเช่นสตริงที่จะอธิบายถึงตัวแปรที่คุณต้องการดึง
คนตัดไม้ $ = getService $ ภาชนะ -> ('utils.logger'); นี้จะมีประสิทธิภาพเทียบเท่ากับการ :
$ = Pro_Logger คนตัดไม้ : : getInstance (); fileWriter = $ Pro_Writer_FileWriter ใหม่ (); $ setHandler Logger -> ($ fileWriter);
มันเป็นไปได้ที่จะตรวจสอบว่าภาชนะบรรจุมีบริการอินสแตนซ์ของโดยการเรียก hasService () วิธีการที่จะส่งกลับค่าบูลีน
มันไม่จำเป็นต้องมีการเข้าถึงที่เก็บเกินกว่าระดับบนสุดของใบสมัครของคุณตั้งแต่ครั้งเรียกตัวอย่างทั้งหมดของการอ้างอิงต้องถูกต้องลงไปที่ระดับความลึกลึกที่สุดของใบสมัครของคุณอยู่แล้วการติดตั้งและรอที่จะเรียกว่า
การทดสอบหน่วย
พึ่งพาการฉีดยังมีสิทธิประโยชน์เพิ่มเติมของวัตถุที่อนุญาตให้มีการทดสอบในการแยก ตัวอย่างเช่นการเรียน DecisionMaker ก่อนดำเนินการติดตั้งหัวฉีดขึ้นต่อผลการทดสอบของเราก็มีขึ้นอยู่กับระดับการดำเนินการตาม DecisionParameters
หากผลการเรียน DecisionParameters ที่แตกต่างกันกลับการทดสอบของเราสามารถเริ่มทำงานได้ผ่านความล้มเหลวของตัวเองไม่มีความผิดของเรา การใช้ยาฉีดพึ่งพาเราสามารถผ่านในขณะนี้ซึ่งจะส่งกลับวัตถุ DecisionParameters ทราบ / คงที่ตั้งของผลสำหรับป้อนพารามิเตอร์บางอย่างเราตอนนี้ทดสอบ DecisionMaker ในการแยกจากปัจจัยภายนอกใด ๆ เช่นถ้าการทดสอบของเราเริ่มต้นล้มเหลวนี้สามารถบันทึกโดยตรงไปยังบางสิ่งบางอย่าง การเปลี่ยนแปลงในชั้นเรียน DecisionMakeer ซึ่งเป็นสิ่งสำคัญโดยเฉพาะอย่างยิ่งหากท่านจะอาศัยการทดสอบข้อมูลจากฐานข้อมูลสำหรับการทดสอบ
การกำหนดค่าการสมัคร
วิธีการที่ใบสมัครของคุณจะทำงานบนเซิร์ฟเวอร์ของคุณย่อมจะแตกต่างจากการตั้งค่าการพัฒนาของคุณ ตัวอย่างเช่นในสภาพแวดล้อมการพัฒนาระดับของการบันทึกจะละเอียดมากขึ้นกว่าในระบบการผลิตของคุณ โดยการเปลี่ยนการพึ่งพาการฉีดภาชนะบรรจุแฟ้มการกำหนดค่าของคุณเล็กน้อย (หรือการแยกวิเคราะห์แฟ้มการกำหนดค่าเพิ่มเติม) การเปลี่ยนแปลงพฤติกรรมขึ้นอยู่กับสภาพแวดล้อมที่สามารถทำได้ง่าย
จำแนกตามประเภท hinting บนอินเตอร์เฟซการใช้งานมากกว่าเมื่อตั้งค่าการอ้างอิงของคุณได้นอกจากนี้ยังสามารถสลับออกมาประกอบการชิ้นส่วนเข้ากันได้กับไม่กี่บรรทัดของ YAML หรือ XML ตัวอย่างเช่นคุณขณะนี้อาจเข้าถึงฐานข้อมูลของคุณผ่าน MySQL DAO (Data Access Object) แต่ในเวลาที่คุณอาจพัฒนา PDO, Zend_Db หรือ ลัทธิ การดำเนินการตาม DAO นี้ โดยการเพิ่มการใช้ใหม่ลงในแฟ้มกำหนดค่าของคุณก็วัตถุทั้งหมดที่ใช้ในการดำเนิน MySQL เก่าตอนนี้ใช้การดำเนินงานใหม่ของคุณโดยไม่จำเป็นต้องโจมตีบาดาลของใบสมัครของคุณ
Notes
- โดยการตั้งค่าที่ใช้ร่วมกัน : เป็นจริงในการกำหนดค่าที่เราจะได้รับอยู่เสมอเช่นเดียวกับวัตถุ ซึ่งจะเป็นประโยชน์มากเมื่อจัดการกับวัตถุที่มีทรัพยากรเช่นการเชื่อมต่อฐานข้อมูล, ไฟล์จัดการและอื่น ๆ
- มีสองวิธีการที่ขึ้นต่อกันสามารถฉีดเป็น หนึ่งคือการส่งผ่านความขึ้นกับตัวสร้างหรืออีกทางเลือกหนึ่งตัวตั้งค่าผ่านทางวิธีการ รูปแบบที่ยอมรับกันโดยทั่วไปจะต้องผ่านการขึ้นต่อกันผ่านทางตัวสร้างและ optionals ผ่าน setters การตั้งค่าส่วนตัวของฉันคือการใช้ setters สำหรับทุกอย่าง แต่นี้ลงไปยังผู้พัฒนารายบุคคล
สุดท้าย ...
พร้อมกับการสนทนาสั้น ๆ จากการฉีดยาพึ่งพาและข้อดีและข้อเสียนี้ยังได้รับคู่มือเริ่มต้นอย่างรวดเร็วในการดำเนินการ Symfony Dependency Injection คอนเทนเนอร์ ... หวังว่าคุณได้เห็นว่ามันน่าแปลกใจที่ง่ายและรวดเร็ว จากที่นี่คุณจะสามารถเริ่มใช้การฉีดขึ้นต่อผ่านการประยุกต์ใช้ของคุณและมองไปที่อื่น ๆ อีกมากมายโดยใช้คุณสมบัติขั้นสูง (แม้ว่าจะเป็นตัวอย่างง่ายๆครอบคลุมส่วนใหญ่ของการทำงานคุณจะต้อง) และเช่นเคยผมชี้ให้คุณสามารถ คู่มือ สำหรับข้อมูลเพิ่มเติม


















































[...] โพสต์นี้ได้กล่าวถึงใน Twitter โดย Vincent Jousse, Steven Lloyd Watkin Steven Lloyd Watkin กล่าวว่า http://bit.ly/cUO2ov เริ่มต้นอย่างรวดเร็วสำหรับการฉีด symfony # # กรอบการพึ่งพา PHP ZF # [...]
บทความยอดเยี่ยม
ผมมีข้อสงสัยในขณะนี้ เมื่อ bootstrapping เราจะโหลดแฟ้มการกำหนดค่า yaml ที่ไม่ให้สร้างวัตถุสำหรับทุกคนที่เราไม่จำเป็นต้อง?
สำหรับเช่น : ฉันมีบางสิ่งบางอย่างชั้นที่จะใช้เพียงบางครั้ง ดังนั้นมันจะสร้างวัตถุหรือมันคือสมาร์ทพอที่จะโหลดผ่านทางฟังก์ชั่น autoload เมื่อฉันโทร getInstance () method ฉันไม่ได้ว่านั่นคือเหตุผลที่
ขอขอบคุณ
ไม่มีชั้นเรียนมีการโหลดเฉพาะเมื่อพวกเขาจะต้องแรก
ใน getInstance () ตัวอย่างเช่นชั้นเป็น instantiated ชอบ
$ ชั้น Class = : : getInstance ();
แทนที่จะ :
class = $ Class ใหม่ ();
โดยทั่วไปจะใช้เมื่อมีการใช้รูปแบบเดี่ยว
[...] ปล่อยให้คุณใช้ DI ในโครงการของคุณในวิธีที่ง่าย Steven Lloyd Watkin ใช้เวลาของเขาในการเขียน tutorial.It เริ่มต้นอย่างรวดเร็วของมูลค่าการพูดถึงว่า Symfony DI คอนเทนเนอร์เป็นห้องสมุดเดี่ยวใช้ได้เป็น Symfony [...]