Symfony - Vùng chứa dịch vụ
Trong bất kỳ ứng dụng nào, các đối tượng có xu hướng tăng lên khi ứng dụng phát triển. Khi các đối tượng tăng lên, sự phụ thuộc giữa các đối tượng cũng tăng lên. Sự phụ thuộc đối tượng cần được xử lý đúng cách để ứng dụng thành công.
Như đã thảo luận trong chương Thành phần, Symfony cung cấp một thành phần dễ dàng và hiệu quả, DependencyInjectionđể xử lý sự phụ thuộc đối tượng. Vùng chứa dịch vụ là một vùng chứa các đối tượng có sự phụ thuộc được giải quyết đúng cách giữa chúng. Hãy để chúng tôi tìm hiểu cách sử dụng thành phần DependencyInjection trong chương này.
Hãy để chúng tôi tạo ra một Greeterlớp học. Mục đích của lớp Greeter là chào hỏi người dùng như trong ví dụ sau.
$greeter = new Greeter('Hi');
$greeter->greet('Jon'); // print "Hi, Jon"
Mã hoàn chỉnh của lớp Greeter như sau.
class Greeter {
private $greetingText;
public function __construct($greetingText) {
$this->greetingText = $greetingText;
}
public function greet($name) {
echo $this->greetingText . ", " . $name . "\r\n";
}
}
Bây giờ, chúng ta hãy thêm lớp Greeter vào vùng chứa dịch vụ. Symfony cung cấpContainerBuilderđể tạo một vùng chứa mới. Khi vùng chứa được tạo, lớp Greeter có thể được đăng ký vào nó bằng phương thức đăng ký của vùng chứa.
use Symfony\Component\DependencyInjection\ContainerBuilder;
$container = new ContainerBuilder();
$container
->register('greeter', 'Greeter')
->addArgument('Hi');
Ở đây, chúng tôi đã sử dụng đối số tĩnh để chỉ định văn bản lời chào, Xin chào. Symfony cũng cung cấp một cài đặt thông số động. Để sử dụng một tham số động, chúng ta cần chọn một tên và chỉ định nó giữa% và tham số có thể được đặt bằng cách sử dụng vùng chứasetParameter phương pháp.
$container = new ContainerBuilder();
$container
->register('greeter', 'Greeter')
->addArgument('%greeter.text%');
$container->setParameter('greeter.text', 'Hi');
Chúng tôi đã đăng ký một lớp học Greeter với thiết lập phù hợp. Bây giờ, chúng ta có thể yêu cầu vùng chứa cung cấp đối tượng Greeter được định cấu hình đúng bằng cách sử dụng vùng chứaget phương pháp.
$greeter = $container->get('greeter');
$greeter->greet('Jon'); // prints "Hi, Jon"
Chúng tôi đã đăng ký thành công một lớp, Greeter vào vùng chứa, lấy nó từ vùng chứa và sử dụng nó. Bây giờ, chúng ta hãy tạo một lớp khácUser, sử dụng lớp Greeter và xem cách đăng ký.
class User {
private $greeter;
public $name;
public $age;
public function setGreeter(\Greeter $greeter) {
$this->greeter = $greeter;
}
public function greet() {
$this->greeter->greet($this->name);
}
}
Lớp Người dùng nhận được lớp Greeter bằng cách sử dụng một trong các phương thức setter của nó,setGreeter. Đối với trường hợp này, Symfony cung cấp một phương pháp,addMethodCall và một lớp học, Reference để tham chiếu một lớp khác như được hiển thị trong đoạn mã sau.
use Symfony\Component\DependencyInjection\Reference;
$container
->register('user', 'User')
->addMethodCall('setGreeter', array(new Reference('greeter')));
Cuối cùng, chúng tôi đã đăng ký hai lớp học, Greeter và Usercó mối quan hệ chặt chẽ giữa chúng. Bây giờ, chúng ta có thể tìm nạp đối tượng Người dùng một cách an toàn với lớp Greeter được định cấu hình đúng từ vùng chứa như được hiển thị trong đoạn mã sau.
$container->setParameter('greeter.text', 'Hi');
$user = $container->get('user');
$user->name = "Jon";
$user->age = 20;
$user->greet(); // Prints "Hi, Jon"
Chúng ta đã thấy cách cấu hình một đối tượng trong vùng chứa bằng chính PHP. Symfony cũng cung cấp các cơ chế khác. Chúng là các tệp cấu hình XML và YAML. Hãy để chúng tôi xem cách định cấu hình vùng chứa bằng YAML. Đối với điều này, cài đặtsymfony/config và symfony/yaml các thành phần cùng với symfony/dependency-injection các thành phần.
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
Cấu hình YAML sẽ được ghi trong một tệp riêng biệt, services.yml. Cấu hình YAML bao gồm hai phần,parameters và services. Phần tham số xác định tất cả các tham số bắt buộc. Phần dịch vụ xác định tất cả các đối tượng. Phần dịch vụ được chia thành nhiều phần cụ thể là,class, arguments, và calls. Lớp xác định lớp thực tế. Các đối số chỉ định các đối số của hàm tạo. Cuối cùng, các cuộc gọi chỉ định các phương thức setter. Một lớp khác có thể được giới thiệu bằng ký hiệu @, @greeter.
parameters:
greeter.text: 'Hello'
services:
greeter:
class: Greeter
arguments: ['%greeter.text%']
user:
class: User
calls:
- [setGreeter, ['@greeter']]
Hiện nay, services.yml có thể được tải và cấu hình bằng cách sử dụng FileLoader và YamlFileLoader như thể hiện trong đoạn mã sau.
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();
Danh sách mã hoàn chỉnh như sau.
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']]
Khung công tác web Symfony sử dụng rộng rãi thành phần tiêm phụ thuộc. Tất cả các thành phần được ràng buộc bởi vùng chứa dịch vụ tập trung. Symfony web framework cho thấy vùng chứa trong tất cảController xuyên qua containerbất động sản. Chúng tôi có thể nhận được tất cả các đối tượng được đăng ký trong đó, chẳng hạn như trình ghi nhật ký, bưu phẩm, v.v., thông qua nó.
$logger = $this->container->get('logger');
$logger->info('Hi');
Để tìm đối tượng đã đăng ký trong vùng chứa, hãy sử dụng lệnh sau.
cd /path/to/app
php bin/console debug:container
Có khoảng hơn 200 đối tượng trong hello ứng dụng web được tạo trong chương cài đặt.