이 글에서는 PHP의 서비스 컨테이너와 의존성 주입에 대해 주로 소개하는데, 이는 어느 정도 참고할만한 가치가 있습니다. 이제 도움이 필요한 친구들이 참고할 수 있도록 하겠습니다.
<?php /** * 定义了一个消息类 * Class Message */ class Message{ public function seed() { return 'seed email'; } } /* * 订单产生的时候 需要发送消息 */ class Order{ protected $messager = ''; function __construct() { $this->messager = new Message(); } public function seed_msg() { return $this->messager->seed(); } } $Order = new Order(); $Order->seed_msg();
Message
클래스를 변경해야 한다는 것을 알게 될 것입니다. Order
클래스에서도 변경해야 합니다. 이것은 매우 귀찮은 것 같습니다. 이때 의존성 주입이라는 아이디어가 탄생했습니다. 코드를 수정해 보겠습니다 <?php /** * 为了约束我们先定义一个消息接口 * Interface Message */ interface Message{ public function seed(); } /** * 有一个发送邮件的类 * Class SeedEmail */ class SeedEmail implements Message { public function seed() { return 'seed email'; // TODO: Implement seed() method. } } /** *新增一个发送短信的类 * Class SeedSMS */ class SeedSMS implements Message { public function seed() { return 'seed sms'; // TODO: Implement seed() method. } } /* * 订单产生的时候 需要发送消息 */ class Order{ protected $messager = ''; function __construct(Message $message) { $this->messager = $message; } public function seed_msg() { return $this->messager->seed(); } } //我们需要发送邮件的时候 $message = new SeedEmail(); //将邮件发送对象作为参数传递给Order $Order = new Order($message); $Order->seed_msg(); //我们需要发送短信的时候 $message = new SeedSMS(); $Order = new Order($message); $Order->seed_msg();
Message
类里面做修改。同样也要再Order
类里面做修改。这样就显得很麻烦。这个时候就有了依赖注入的思路。下面把代码做一个调整<?php /** * 为了约束我们先定义一个消息接口 * Interface Message */ interface Message{ public function seed(); } /** * 有一个发送邮件的类 * Class SeedEmail */ class SeedEmail implements Message { public function seed() { return 'seed email'; // TODO: Implement seed() method. } } /** *新增一个发送短信的类 * Class SeedSMS */ class SeedSMS implements Message { public function seed() { return 'seed sms'; // TODO: Implement seed() method. } } /** * 这是一个简单的服务容器 * Class Container */ class Container { protected $binds; protected $instances; public function bind($abstract, $concrete) { if ($concrete instanceof Closure) { $this->binds[$abstract] = $concrete; } else { $this->instances[$abstract] = $concrete; } } public function make($abstract, $parameters = []) { if (isset($this->instances[$abstract])) { return $this->instances[$abstract]; } array_unshift($parameters, $this); return call_user_func_array($this->binds[$abstract], $parameters); } } //创建一个消息工厂 $message = new Container(); //将发送短信注册绑定到工厂里面 $message->bind('SMS',function (){ return new SeedSMS(); }); //将发送邮件注册绑定到工厂 $message->bind('EMAIL',function (){ return new SeedEmail(); }); //需要发送短信的时候 $SMS = $message->make('SMS'); $SMS->seed();
这样我们就实现了依赖注入的思路,是不是很方便扩展了。
我理解的服务容器就是一个自动产生类的工厂。
$sms = new SeedSMS(); $message->bind('SMS',$sms);
container
是一个简单的服务容器里面有bind
,make
两个方法bind
是向容器中绑定服务对象。make
则是从容器中取出对象。
在bind
方法中需要传入一个 concrete
我们可以传入一个实例对象或者是一个闭包函数。
可以看到我这全使用的是闭包函数,其实也可以这样写
后面这种写法与闭包相比的区别就是我们需要先实例化对象才能往容易中绑定服务。而闭包则是我们使用这个服务的时候才去实例化对象。可以看出闭包是有很多的优势的。
make
方法就从容器中出去方法。里面首先判断了instances
变量中是否有当前以及存在的服务对象,如果有直接返回。如果没有那么会通过 call_user_func_array
返回一个对象。call_user_func_array
이렇게 해서 의존성 주입 아이디어를 실현했습니다. 확장하기가 매우 편리할까요?
rrreee
container
는 bind
및 make
라는 두 가지 메서드가 있는 간단한 서비스 컨테이너입니다. 바인딩은 서비스 개체를 컨테이너에 바인딩하는 것입니다. make
는 컨테이너에서 객체를 가져옵니다. bind
bind
메소드에서는 concrete
를 전달해야 합니다. 인스턴스 객체를 전달할 수 있습니다. 또는 패키지 기능.
클로저 함수를 사용하고 있음을 알 수 있습니다. 실제로 이렇게 작성할 수도 있습니다.
후자의 작성 방법과 클로저의 차이점은 인스턴스화해야 한다는 것입니다. 먼저 개체를 쉽게 바인딩하세요. 클로저는 이 서비스를 사용할 때만 객체를 인스턴스화합니다. 클로저에는 많은 장점이 있음을 알 수 있습니다. make
make
메소드는 컨테이너를 종료하는 메소드입니다. 먼저 instances
변수에 현재 및 기존 서비스 개체가 있는지 확인하고, 있으면 직접 반환합니다. 그렇지 않은 경우 call_user_func_array
를 통해 개체가 반환됩니다. call_user_func_array
사용에 대해서는
PHP에서 call_user_func 사용
위 내용은 PHP의 서비스 컨테이너 및 종속성 주입 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!