>  기사  >  백엔드 개발  >  PHP의 서비스 컨테이너 및 종속성 주입 분석

PHP의 서비스 컨테이너 및 종속성 주입 분석

不言
不言원래의
2018-07-06 13:55:383225검색

이 글에서는 PHP의 서비스 컨테이너와 의존성 주입에 대해 주로 소개하는데, 이는 어느 정도 참고할만한 가치가 있습니다. 이제 도움이 필요한 친구들이 참고할 수 있도록 하겠습니다.

의존성 주입#🎜 🎜 #

클래스 A가 클래스 B에 의존해야 할 때, 즉 클래스 B의 객체를 사용하기 위해 클래스 A에서 인스턴스화해야 할 때 클래스 B의 함수가 변경되면 사용도 발생합니다. 클래스 A의 클래스 B. 클래스도 그에 따라 수정되어야 하므로 클래스 A와 클래스 B 간의 결합이 높아집니다. 이때의 해결책은 클래스 A가 클래스 B의 인터페이스에 의존하고 특정 클래스의 인스턴스화를 외부에 넘겨주는 것입니다.
우리 사업에서 일반적으로 사용되는 알림 모듈을 예로 들어 보겠습니다.

<?php

/**
 * 定义了一个消息类
 * Class Message 
 */
class  Message{

  public function seed()
  {
      return &#39;seed email&#39;;

  }
}
/*
 * 订单产生的时候 需要发送消息
 */
class Order{

    protected $messager = &#39;&#39;;

    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  &#39;seed email&#39;;

        // TODO: Implement seed() method.
    }

}

/** 
 *新增一个发送短信的类
 * Class SeedSMS
 */
class SeedSMS implements Message
{
    public function seed()
    {
        return &#39;seed sms&#39;;
        // TODO: Implement seed() method.
    }


}
/*
 * 订单产生的时候 需要发送消息
 */
class Order{

    protected $messager = &#39;&#39;;

    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  &#39;seed email&#39;;

        // TODO: Implement seed() method.
    }

}

/**
 *新增一个发送短信的类
 * Class SeedSMS
 */
class SeedSMS implements Message
{
    public function seed()
    {
        return &#39;seed sms&#39;;
        // 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(&#39;SMS&#39;,function (){
     return   new  SeedSMS();
});
//将发送邮件注册绑定到工厂
$message->bind(&#39;EMAIL&#39;,function (){
   return new  SeedEmail();
});
//需要发送短信的时候
$SMS  = $message->make(&#39;SMS&#39;);
$SMS->seed();

这样我们就实现了依赖注入的思路,是不是很方便扩展了。

服务容器

我理解的服务容器就是一个自动产生类的工厂。
$sms = new  SeedSMS();
$message->bind('SMS',$sms);

container是一个简单的服务容器里面有bind,make两个方法
bind是向容器中绑定服务对象。make则是从容器中取出对象。

bind

bind方法中需要传入一个 concrete 我们可以传入一个实例对象或者是一个闭包函数。
可以看到我这全使用的是闭包函数,其实也可以这样写

rrreee

后面这种写法与闭包相比的区别就是我们需要先实例化对象才能往容易中绑定服务。而闭包则是我们使用这个服务的时候才去实例化对象。可以看出闭包是有很多的优势的。

make

make方法就从容器中出去方法。里面首先判断了instances变量中是否有当前以及存在的服务对象,如果有直接返回。如果没有那么会通过 call_user_func_array返回一个对象。call_user_func_array 이렇게 해서 의존성 주입 아이디어를 실현했습니다. 확장하기가 매우 편리할까요?

서비스 컨테이너

내가 이해하는 서비스 컨테이너는 자동으로 클래스를 생성하는 팩토리입니다.

rrreee

containerbindmake

라는 두 가지 메서드가 있는 간단한 서비스 컨테이너입니다. 바인딩은 서비스 개체를 컨테이너에 바인딩하는 것입니다. make는 컨테이너에서 객체를 가져옵니다.

bind

bind 메소드에서는 concrete를 전달해야 합니다. 인스턴스 객체를 전달할 수 있습니다. 또는 패키지 기능.
클로저 함수를 사용하고 있음을 알 수 있습니다. 실제로 이렇게 작성할 수도 있습니다.

rrreee

후자의 작성 방법과 클로저의 차이점은 인스턴스화해야 한다는 것입니다. 먼저 개체를 쉽게 바인딩하세요. 클로저는 이 서비스를 사용할 때만 객체를 인스턴스화합니다. 클로저에는 많은 장점이 있음을 알 수 있습니다.

make

make 메소드는 컨테이너를 종료하는 메소드입니다. 먼저 instances 변수에 현재 및 기존 서비스 개체가 있는지 확인하고, 있으면 직접 반환합니다. 그렇지 않은 경우 call_user_func_array를 통해 개체가 반환됩니다. call_user_func_array 사용에 대해서는
PHP에서 call_user_func 사용

#🎜🎜# PHP 컨테이너 Pimple 실행 프로세스 분석 #🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜# gitbash PHP 실행 출력 중국어 혼돈에 대한 솔루션 #🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜#PHP에서 일반적으로 사용되는 배열 함수#🎜🎜##🎜🎜##🎜🎜#

위 내용은 PHP의 서비스 컨테이너 및 종속성 주입 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.