Symfony - คอนเทนเนอร์บริการ
ในแอปพลิเคชันใด ๆ วัตถุมักจะเพิ่มขึ้นเมื่อแอปพลิเคชันเติบโตขึ้น เมื่อวัตถุเพิ่มขึ้นการพึ่งพาระหว่างวัตถุก็เพิ่มขึ้นเช่นกัน การพึ่งพาวัตถุต้องได้รับการจัดการอย่างเหมาะสมเพื่อให้แอปพลิเคชันประสบความสำเร็จ
ตามที่กล่าวไว้ในบทส่วนประกอบ Symfony มีส่วนประกอบที่ง่ายและมีประสิทธิภาพ DependencyInjectionเพื่อจัดการการพึ่งพาวัตถุ คอนเทนเนอร์บริการคือที่เก็บของออบเจ็กต์ที่มีการแก้ไขการพึ่งพาระหว่างกันอย่างเหมาะสม ให้เราเรียนรู้วิธีใช้ส่วนประกอบ DependencyInjection ในบทนี้
ให้เราสร้างไฟล์ Greeterชั้นเรียน วัตถุประสงค์ของคลาส Greeter คือเพื่อทักทายผู้ใช้ดังที่แสดงในตัวอย่างต่อไปนี้
$greeter = new Greeter('Hi');
$greeter->greet('Jon'); // print "Hi, Jon"
รหัสที่สมบูรณ์ของคลาส Greeter มีดังนี้
class Greeter {
private $greetingText;
public function __construct($greetingText) {
$this->greetingText = $greetingText;
}
public function greet($name) {
echo $this->greetingText . ", " . $name . "\r\n";
}
}
ตอนนี้ให้เราเพิ่มคลาส Greeter ลงในที่เก็บบริการ Symfony ให้ContainerBuilderเพื่อสร้างคอนเทนเนอร์ใหม่ เมื่อสร้างคอนเทนเนอร์แล้วคลาส Greeter สามารถลงทะเบียนได้โดยใช้วิธีการลงทะเบียนของคอนเทนเนอร์
use Symfony\Component\DependencyInjection\ContainerBuilder;
$container = new ContainerBuilder();
$container
->register('greeter', 'Greeter')
->addArgument('Hi');
ที่นี่เราได้ใช้อาร์กิวเมนต์คงที่เพื่อระบุข้อความทักทายสวัสดี Symfony มีการตั้งค่าพารามิเตอร์แบบไดนามิกเช่นกัน ในการใช้พารามิเตอร์แบบไดนามิกเราต้องเลือกชื่อและระบุระหว่าง% และพารามิเตอร์สามารถตั้งค่าได้โดยใช้คอนเทนเนอร์setParameter วิธี.
$container = new ContainerBuilder();
$container
->register('greeter', 'Greeter')
->addArgument('%greeter.text%');
$container->setParameter('greeter.text', 'Hi');
เราได้ลงทะเบียนคลาส Greeter ด้วยการตั้งค่าที่เหมาะสม ตอนนี้เราสามารถขอให้คอนเทนเนอร์จัดเตรียมวัตถุ Greeter ที่กำหนดค่าไว้อย่างเหมาะสมโดยใช้คอนเทนเนอร์get วิธี.
$greeter = $container->get('greeter');
$greeter->greet('Jon'); // prints "Hi, Jon"
เราได้ลงทะเบียนคลาส Greeter ลงในคอนเทนเนอร์เรียบร้อยแล้วดึงมาจากคอนเทนเนอร์และใช้งานได้ ตอนนี้ให้เราสร้างคลาสอื่นUserซึ่งใช้คลาส Greeter และดูวิธีการลงทะเบียน
class User {
private $greeter;
public $name;
public $age;
public function setGreeter(\Greeter $greeter) {
$this->greeter = $greeter;
}
public function greet() {
$this->greeter->greet($this->name);
}
}
คลาส User รับคลาสGreeterโดยใช้หนึ่งในเมธอด settersetGreeter. สำหรับสถานการณ์นี้ Symfony มีวิธีการaddMethodCall และชั้นเรียน Reference เพื่ออ้างถึงคลาสอื่นตามที่แสดงในโค้ดต่อไปนี้
use Symfony\Component\DependencyInjection\Reference;
$container
->register('user', 'User')
->addMethodCall('setGreeter', array(new Reference('greeter')));
ในที่สุดเราก็ได้ลงทะเบียนสองคลาส Greeter และ Userมีความสัมพันธ์ที่ดีระหว่างพวกเขา ตอนนี้เราสามารถดึงอ็อบเจ็กต์ User ได้อย่างปลอดภัยด้วยคลาส Greeter ที่กำหนดค่าอย่างถูกต้องจากคอนเทนเนอร์ดังที่แสดงในโค้ดต่อไปนี้
$container->setParameter('greeter.text', 'Hi');
$user = $container->get('user');
$user->name = "Jon";
$user->age = 20;
$user->greet(); // Prints "Hi, Jon"
เราได้เห็นวิธีกำหนดค่าวัตถุในคอนเทนเนอร์โดยใช้ PHP เอง Symfony มีกลไกอื่น ๆ ด้วย เป็นไฟล์คอนฟิกูเรชัน XML และ YAML ให้เราดูวิธีกำหนดค่าคอนเทนเนอร์โดยใช้ YAML สำหรับสิ่งนี้ให้ติดตั้งsymfony/config และ symfony/yaml ส่วนประกอบพร้อมด้วย symfony/dependency-injection ส่วนประกอบ
cd /path/to/dir
mkdir dependency-injection-example
cd dependency-injection-example
composer require symfony/dependency-injection
composer require symfony/config
composer require symfony/yaml
การกำหนดค่า YAML จะเขียนในไฟล์แยกต่างหาก services.yml. การกำหนดค่า YAML ประกอบด้วยสองส่วนparameters และ services. ส่วนพารามิเตอร์กำหนดพารามิเตอร์ที่จำเป็นทั้งหมด ส่วนบริการกำหนดวัตถุทั้งหมด ส่วนบริการยังแบ่งออกเป็นหลายส่วน ได้แก่class, arguments, และ calls. คลาสระบุคลาสจริง อาร์กิวเมนต์ระบุอาร์กิวเมนต์ของตัวสร้าง สุดท้ายการโทรระบุเมธอด setter สามารถอ้างอิงคลาสอื่นได้โดยใช้สัญลักษณ์ @, @greeter
parameters:
greeter.text: 'Hello'
services:
greeter:
class: Greeter
arguments: ['%greeter.text%']
user:
class: User
calls:
- [setGreeter, ['@greeter']]
ตอนนี้ services.yml สามารถโหลดและกำหนดค่าโดยใช้ไฟล์ FileLoader และ YamlFileLoader ดังแสดงในรหัสต่อไปนี้
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
$yamlContainer = new ContainerBuilder();
$loader = new YamlFileLoader($yamlContainer, new FileLocator(__DIR__));
$loader->load('services.yml');
$yamlUser = $yamlContainer->get('user');
$yamlUser->name = "Jon";
$yamlUser->age = 25;
$yamlUser->greet();
รายการรหัสที่สมบูรณ์มีดังนี้
main.php
<?php
require __DIR__ . '/vendor/autoload.php';
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
class Greeter {
private $greetingText;
public function __construct($greetingText) {
$this->greetingText = $greetingText;
}
public function greet($name) {
echo $this->greetingText . ", " . $name . "\r\n";
}
}
class User {
private $greeter;
public $name;
public $age;
public function setGreeter(\Greeter $greeter) {
$this->greeter = $greeter;
}
public function greet() {
$this->greeter->greet($this->name);
}
}
$container = new ContainerBuilder();
$container
->register('greeter', 'Greeter')
->addArgument('%greeter.text%');
$container
->register('user', 'User')
->addMethodCall('setGreeter', array(new Reference('greeter')));
$container->setParameter('greeter.text', 'Hi');
$greeter = $container->get('greeter');
$greeter->greet('Jon');
$user = $container->get('user');
$user->name = "Jon";
$user->age = 20;
$user->greet();
$yamlContainer = new ContainerBuilder();
$loader = new YamlFileLoader($yamlContainer, new FileLocator(__DIR__));
$loader->load('services.yml');
$yamlHello = $yamlContainer->get('greeter');
$yamlHello->greet('Jon');
$yamlUser = $yamlContainer->get('user');
$yamlUser->name = "Jon";
$yamlUser->age = 25;
$yamlUser->greet();
?>
services.yml
parameters:
greeter.text: 'Hello'
services:
greeter:
class: Greeter
arguments: ['%greeter.text%']
user:
class: User
calls:
- [setGreeter, ['@greeter']]
เฟรมเวิร์กเว็บ Symfony ใช้องค์ประกอบการฉีดขึ้นต่อกันอย่างกว้างขวาง ส่วนประกอบทั้งหมดถูกผูกไว้โดยคอนเทนเนอร์บริการส่วนกลาง เว็บเฟรมเวิร์ก Symfony แสดงคอนเทนเนอร์ในไฟล์Controller ผ่าน containerทรัพย์สิน. เราสามารถลงทะเบียนวัตถุทั้งหมดในนั้นพูดคนตัดไม้จดหมาย ฯลฯ ผ่านมัน
$logger = $this->container->get('logger');
$logger->info('Hi');
หากต้องการค้นหาวัตถุที่ลงทะเบียนในคอนเทนเนอร์ให้ใช้คำสั่งต่อไปนี้
cd /path/to/app
php bin/console debug:container
มีวัตถุมากกว่า 200 รายการในไฟล์ hello เว็บแอปที่สร้างขึ้นในบทการติดตั้ง