지금까지 몇 가지 기본 개념에 대해 이야기했습니다. 처음 두 기사의 예는 종속성 주입 구현을 이해하는 데 매우 도움이 됩니다. 이제 Symfony 2 서비스 컨테이너 구현에 대해 자세히 살펴보겠습니다.
Symfony의 종속성 주입 컨테이너는 sfServiceContainer라는 클래스에 의해 관리됩니다.
Symfony 컨테이너는 독립적인 구성 요소로 존재할 수 있습니다. Symfony의 공식 Subversion 저장소는 http://svn .symfony-에서 다운로드할 수 있습니다. project.com/comComponents/dependent_injection/trunk/
. 이 구성 요소는 아직 지속적인 반복 개발 중이므로 언제든지 업데이트될 수 있다는 점에 주목할 필요가 있습니다(2009년에 언급되었으나 지금은 중단된 것 같습니다).
심포니의 디자인 철학에 따르면 모든 서비스는 컨테이너로 관리되는 객체가 될 수 있습니다. 이전 글에서 소개한 Zend_Mail 예제에는 mailer와 mail_transport라는 두 개의 객체가 있습니다
class Container { static protected $shared = array(); protected $parameters = array(); public function __construct(array $parameters = array()) { $this->parameters = $parameters; } public function getMailTransport() { return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array( 'auth' => 'login', 'username' => $this->parameters['mailer.username'], 'password' => $this->parameters['mailer.password'], 'ssl' => 'ssl', 'port' => 465, )); } public function getMailer() { if (isset(self::$shared['mailer'])) { return self::$shared['mailer']; } $class = $this->parameters['mailer.class']; $mailer = new $class(); $mailer->setDefaultTransport($this->getMailTransport()); return self::$shared['mailer'] = $mailer; } }
Container 클래스가 Symfony의 sfServiceContainer 클래스를 상속받는다면 코드를 좀 더 간단하게 만들 수 있습니다
class Container extends sfServiceContainer { static protected $shared = array(); protected function getMailTransportService() { return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array( 'auth' => 'login', 'username' => $this['mailer.username'], 'password' => $this['mailer.password'], 'ssl' => 'ssl', 'port' => 465, )); } protected function getMailerService() { if (isset(self::$shared['mailer'])) { return self::$shared['mailer']; } $class = $this['mailer.class']; $mailer = new $class(); $mailer->setDefaultTransport($this->getMailTransportService()); return self::$shared['mailer'] = $mailer; } }
관찰: 생성자 및 매개변수 구성 관리 코드가 생략되었습니다.
그러나 그것이 전부는 아닙니다. sfServiceContainer는 인터페이스를 사용할 때 주의해야 할 몇 가지 사항입니다.
1. 서비스. 일반적으로 메소드 이름은 get으로 시작하고 Service로 끝나는 데 동의합니다. 각 서비스에는 고유한 로고가 있습니다. 로고는 일반적으로 접두사와 접미사가 없고 밑줄로 구분된 메서드 이름입니다. getMailTransportService() 메소드가 정의된 경우 서비스 이름은 mail_transport
2. 메소드는 보호 유형이므로 서비스를 얻기 위해 메소드를 직접 호출할 수 없습니다. 컨테이너를 사용하여 서비스를 얻는 방법은 나중에 소개하겠습니다.
3. 전달된 매개변수를 얻기 위해 컨테이너에 배열로 액세스할 수 있습니다. 예: $this['mailer.class']
서비스 표시는 고유해야 하며 문자, 숫자, '_' 및 '.'로만 구성될 수 있습니다. '.'는 네임스페이스(예: mail.mailer 및 mail.transport)로 사용될 수 있습니다.
이제 이 새로운 컨테이너를 어떻게 사용하는지 살펴보겠습니다
require_once 'PATH/TO/sf/lib/sfServiceContainerAutoloader.php'; sfServiceContainerAutoloader::register(); $sc = new Container(array( 'mailer.username' => 'foo', 'mailer.password' => 'bar', 'mailer.class' => 'Zend_Mail', )); $mailer = $sc->mailer;
Container 클래스는 sfServiceContainer를 상속받기 때문에 인터페이스가 매우 깔끔해집니다.
통합 인터페이스를 통해 서비스에 액세스
if ($sc->hasService('mailer')) { $mailer = $sc->getService('mailer'); } $sc->setService('mailer', $mailer);
더 간단한 방법은 속성을 통해 서비스에 액세스하는 것입니다
if (isset($sc->mailer)) { $mailer = $sc->mailer; } $sc->mailer = $mailer;매개변수는 통합 인터페이스를 통해 액세스합니다. 인터페이스
if (!$sc->hasParameter('mailer_class')) { $sc->setParameter('mailer_class', 'Zend_Mail'); } echo $sc->getParameter('mailer_class'); // Override all parameters of the container $sc->setParameters($parameters); // Adds parameters $sc->addParameters($parameters);
매개변수는 배열처럼 컨테이너를 통해서도 액세스할 수 있습니다.
if (!isset($sc['mailer.class'])) { $sc['mailer.class'] = 'Zend_Mail'; } $mailerClass = $sc['mailer.class'];
컨테이너는 iterator, 모든 서비스 순회
foreach ($sc as $id => $service) { echo sprintf("Service %s is an instance of %s.\n", $id, get_class($service)); }
관리할 서비스가 많지 않은 경우 기본적인 작업도 많이 하고 코드도 많이 복사해야 하지만, sfServiceContainer를 사용하는 것이 매우 유용하다는 것을 인정합니다.
관리해야 할 서비스가 점점 더 많아진다면, 서비스를 더 잘 설명할 수 있는 방법이 있어야 합니다.
이것이 대부분의 경우 sfServiceContainer 클래스를 직접 사용하지 않는 이유입니다. 그럼에도 불구하고 Symfony 종속성 주입 컨테이너의 중요한 초석이기 때문에 그것에 대해 이야기하는 데 시간을 할애할 필요가 있습니다.
위 내용은 PHP 의존성 주입 컨테이너 시리즈 이해 내용입니다. (3) Symfony 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요!