Open nattapong99 opened 6 years ago
ด้วยการแนะนำไฟล์ XML และ YAML config คุณอาจมีความสงสัยเกี่ยวกับประสิทธิภาพของตัว container แม้ว่า service มีการโหลดแบบ lazy loading, การอ่านกลุ่มไฟล์ XML หรือ YAML ในแต่ละ request และการสร้าง object โดยการใช้ introspection อาจไม่มีค่อยมีประสิทธิภาพในภาษา PHP และเนื่องจาก container เป็นเกือบทุกส่วนของแอพพลิเคชั่นใด ๆ ก็ตามที่ใช้มัน จึงทำให้ความเร็วเป็นเรื่องที่สำคัญเช่นกัน
ในแง่หนึ่ง การใช้ XML หรือ YAML ในการกำหนด service นั้นมีประสิทธิภาพและมีความยืดหยุ่นมาก
[php] <container xmlns="http://symfony-project.org/2.0/container"> <parameters> <parameter key="mailer.username">foo</parameter> <parameter key="mailer.password">bar</parameter> <parameter key="mailer.class">Zend_Mail</parameter> </parameters> <services> <service id="mail.transport" class="Zend_Mail_Transport_Smtp" shared="false"> <argument>smtp.gmail.com</argument> <argument type="collection"> <argument key="auth">login</argument> <argument key="username">%mailer.username%</argument> <argument key="password">%mailer.password%</argument> <argument key="ssl">ssl</argument> <argument key="port">true</argument> </argument> </service> <service id="mailer" class="%mailer.class%"> <call method="setDefaultTransport"> <argument type="service" id="mail.transport" /> </call> </service> </services> </container>
แต่ในทางกลับกัน การระบุ service container เป็นคลาส PHP ธรรมดาให้ความเร็วกับคุณ
จากโค้ดข้างบนเพื่อให้ยังมีความยืดหยุ่นจึงต้องใช้ตัวแปร configuration และสามารถคงความเร็วได้อยู่
คุณจะทำอย่างไรเพื่อให้ได้ทั้งสองสิ่งที่ดีที่สุด คำตอบนั้นง่ายมาก โดย Dependency Injection component ของ Symfony ยังมีตัว built-in dumper อีกตัวคือ PHP dumper ด้วย dumper ตัวนี้สามารถแปลง service container ใด ๆ ก็ตามให้กลายเป็นคลาส PHP ธรรมดาได้ ซึ่งมันสามารถช่วยในการ generate code ของคุณ
จากตัวอย่าง Zend_Mail
Zend_Mail
คลาส sfServiceContainerDumperPhp ต้องการ container เป็นอาร์กิวเมนต์ตัวแรกสำหรับ constructor โดยเมธอด dump() ใช้อาร์เรย์ของอ็อพชันและหนึ่งในนั้นเป็นชื่อของคลาสที่สร้างขึ้น
sfServiceContainerDumperPhp
dump()
นี่คือ generated code ที่ได้
ถ้าคุณได้เห็น generated code ที่เกิดขึ้นโดย dumper คุณจะสังเกตุเห็นว่าโค้ดมีความคล้ายคลึงกับที่เราเขียนเอง
การ generated code ไม่ได้ใช้คีย์ลัดเพื่อเข้าถึง parameter และ service
ด้วยการใช้ sfServiceContainerDumperPhp ทำให้คุณมีทั้งสองสิ่งที่ดีที่สุดคือ ความยืดหยุ่นที่มาจากรูปแบบไฟล์ XML หรือ YAML ที่ใช้สำหรับการ config service และความเร็วที่มาจาก optimized และ auto-generated ไฟล์ PHP
เป็นที่แน่นอนว่าโปรเจ็คต่าง ๆ มีการตั้งค่าที่แตกต่างกันไปสำหรับ environment ที่แตกต่างกัน คุณสามารถสร้างคลาส container ที่แตกต่างกันเพื่อใช้กับ environment นั้น ๆ หรือใช้กับการตั้งค่า debugging ต่อไปนี้เป็นตัวอย่าง PHP code ที่อธิบายวิธีการสร้าง container แบบไดนามิกสำหรับ first request และใช้ cached สำหรับ request อื่น ๆ ทั้งหมดเมื่อไม่ได้อยู่ใน debugging mode
ก่อนที่จะจบบทความ มีคุณสมบัติดี ๆ อย่างนึงของ dumpper ที่อยากแสดงให้เห็น โดย Dumper สามารถทำสิ่งต่าง ๆ ได้มากมายและเพื่อให้เห็นภาพของการลดการยึดติดของการใช้งาน component เพื่อช่วยให้คุณมองเห็นภาพ service และ dependency ของมัน จึงได้นำ Graphviz dumper มาใช้งาน
ลองดูวิธีการใช้งานจากตัวอย่าง
Graphviz dumper สร้างการแสดงผลแบบ dot ใน container ของคุณ
digraph sc { ratio="compress" node [fontsize="11" fontname="Myriad" shape="record"]; edge [fontsize="9" fontname="Myriad" color="grey" arrowhead="open" arrowsize="0.5"]; node_service_container [label="service_container\nsfServiceContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"]; node_mail_transport [label="mail.transport\nZend_Mail_Transport_Smtp\n", shape=record, fillcolor="#eeeeee", style="dotted"]; node_mailer [label="mailer\nZend_Mail\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_mailer -> node_mail_transport [label="setDefaultTransport()" style="dashed"]; }
การแสดงผลสามารถแปลงเป็นรูปภาพได้โดยใช้ dot_program
จากตัวอย่าง ภาพที่เห็นอาจไม่มีการเพิ่มค่าจริง ๆ แต่เมื่อคุณมี sevice เพิ่มมากขึ้น มันจะมีประโยชน์และสามารถช่วยคุณได้
The Graphviz dumper เมธอด dump() มีความสามารถที่จะแสดงกราฟในแบบต่าง ๆ ได้ graph: ตัวเลือกเริ่มต้นสำหรับกราฟ node: ตัวเลือกเริ่มต้นสำหรับ nodes edge: ตัวเลือกเรื่มต้นสำหรับ edges node.instance: ตัวเลือกเริ่มต้นสำหรับ service โดยสามารถระบุได้โดยตรงผ่าน object instance node.definition: ตัวเลือกเริ่มต้นสำหรับ service โดยสามารถระบุผ่าน service definition instances node.missing: ตัวเลือกเริ่มต้นสำหรับ missing service
The Graphviz dumper เมธอด dump() มีความสามารถที่จะแสดงกราฟในแบบต่าง ๆ ได้
graph
node
edge
node.instance
node.definition
node.missing
นี่คือกราฟสำหรับ hypothetic CMS ที่ใช้กับ Symfony 2 new Templating Framework
จากบทความทั้งหมดของ Dependency Injection ที่ผ่านมา หวังว่าคุณจะได้เรียนรู้อะไรบางอย่างจากการอ่านบทความนี้
source
Symfony Service Container: The Need for Speed
ด้วยการแนะนำไฟล์ XML และ YAML config คุณอาจมีความสงสัยเกี่ยวกับประสิทธิภาพของตัว container แม้ว่า service มีการโหลดแบบ lazy loading, การอ่านกลุ่มไฟล์ XML หรือ YAML ในแต่ละ request และการสร้าง object โดยการใช้ introspection อาจไม่มีค่อยมีประสิทธิภาพในภาษา PHP และเนื่องจาก container เป็นเกือบทุกส่วนของแอพพลิเคชั่นใด ๆ ก็ตามที่ใช้มัน จึงทำให้ความเร็วเป็นเรื่องที่สำคัญเช่นกัน
ในแง่หนึ่ง การใช้ XML หรือ YAML ในการกำหนด service นั้นมีประสิทธิภาพและมีความยืดหยุ่นมาก
แต่ในทางกลับกัน การระบุ service container เป็นคลาส PHP ธรรมดาให้ความเร็วกับคุณ
จากโค้ดข้างบนเพื่อให้ยังมีความยืดหยุ่นจึงต้องใช้ตัวแปร configuration และสามารถคงความเร็วได้อยู่
คุณจะทำอย่างไรเพื่อให้ได้ทั้งสองสิ่งที่ดีที่สุด คำตอบนั้นง่ายมาก โดย Dependency Injection component ของ Symfony ยังมีตัว built-in dumper อีกตัวคือ PHP dumper ด้วย dumper ตัวนี้สามารถแปลง service container ใด ๆ ก็ตามให้กลายเป็นคลาส PHP ธรรมดาได้ ซึ่งมันสามารถช่วยในการ generate code ของคุณ
จากตัวอย่าง
Zend_Mail
คลาส
sfServiceContainerDumperPhp
ต้องการ container เป็นอาร์กิวเมนต์ตัวแรกสำหรับ constructor โดยเมธอดdump()
ใช้อาร์เรย์ของอ็อพชันและหนึ่งในนั้นเป็นชื่อของคลาสที่สร้างขึ้นนี่คือ generated code ที่ได้
ถ้าคุณได้เห็น generated code ที่เกิดขึ้นโดย dumper คุณจะสังเกตุเห็นว่าโค้ดมีความคล้ายคลึงกับที่เราเขียนเอง
ด้วยการใช้
sfServiceContainerDumperPhp
ทำให้คุณมีทั้งสองสิ่งที่ดีที่สุดคือ ความยืดหยุ่นที่มาจากรูปแบบไฟล์ XML หรือ YAML ที่ใช้สำหรับการ config service และความเร็วที่มาจาก optimized และ auto-generated ไฟล์ PHPเป็นที่แน่นอนว่าโปรเจ็คต่าง ๆ มีการตั้งค่าที่แตกต่างกันไปสำหรับ environment ที่แตกต่างกัน คุณสามารถสร้างคลาส container ที่แตกต่างกันเพื่อใช้กับ environment นั้น ๆ หรือใช้กับการตั้งค่า debugging ต่อไปนี้เป็นตัวอย่าง PHP code ที่อธิบายวิธีการสร้าง container แบบไดนามิกสำหรับ first request และใช้ cached สำหรับ request อื่น ๆ ทั้งหมดเมื่อไม่ได้อยู่ใน debugging mode
ก่อนที่จะจบบทความ มีคุณสมบัติดี ๆ อย่างนึงของ dumpper ที่อยากแสดงให้เห็น โดย Dumper สามารถทำสิ่งต่าง ๆ ได้มากมายและเพื่อให้เห็นภาพของการลดการยึดติดของการใช้งาน component เพื่อช่วยให้คุณมองเห็นภาพ service และ dependency ของมัน จึงได้นำ Graphviz dumper มาใช้งาน
ลองดูวิธีการใช้งานจากตัวอย่าง
Graphviz dumper สร้างการแสดงผลแบบ dot ใน container ของคุณ
การแสดงผลสามารถแปลงเป็นรูปภาพได้โดยใช้ dot_program
จากตัวอย่าง ภาพที่เห็นอาจไม่มีการเพิ่มค่าจริง ๆ แต่เมื่อคุณมี sevice เพิ่มมากขึ้น มันจะมีประโยชน์และสามารถช่วยคุณได้
นี่คือกราฟสำหรับ hypothetic CMS ที่ใช้กับ Symfony 2 new Templating Framework
จากบทความทั้งหมดของ Dependency Injection ที่ผ่านมา หวังว่าคุณจะได้เรียนรู้อะไรบางอย่างจากการอ่านบทความนี้
source