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 เว็บแอปที่สร้างขึ้นในบทการติดตั้ง