PHP 프레임워크 구축: 7부 - 컨테이너

13223 단어 phpwebdev
Orginially Posted on DevelopmentMatt.com

Part 6에서 PHP 컨테이너에 대한 논의를 시작했습니다. 오늘은 주제에 대해 더 자세히 설명하고 분석 컨테이너에서 지금까지 수행한 작업을 살펴보겠습니다.

PHP League Container 등의 배후에 있는 사람들에게 큰 감사의 빚을 지고 있습니다. 나는 그들의 코드를 공부하면서 많은 것을 배웠습니다.

빠른 요약



컨테이너는 무엇이며 왜 사용합니까? 컨테이너는 개체로 구성된 레지스트리이자 개체를 검색하는 메커니즘입니다. 말하자면 도서관과 사서입니다. 컨테이너는 개발자에게 종속성을 보다 쉽게 ​​관리할 수 있는 도구를 제공합니다.

분석 컨테이너



Analyze 프레임워크에서 사용될 컨테이너에 대한 작업이 시작되었으며 이 글을 쓰는 시점에서 기본적으로 기초가 완성되었습니다. 아직 끝나지 않았지만 논의하기에 충분하다는 점을 명심하십시오.

All of the code for the container can be found on Github.

간단한 예



현재 컨테이너에 개체를 등록하는 방법에는 두 가지가 있습니다. 첫 번째는 공장을 사용하는 것입니다. 팩토리는 클로저를 사용하여 검색 시 객체를 빌드합니다.

$container = new Container;

$container->addFactory('Carbon', function () {
    return new \Carbon\Carbon;
});

$carbon = $container->get('Carbon');

var_dump($carbon->year) // 2018


두 번째 옵션은 정규화된 이름을 사용하여 클래스를 등록하는 것입니다.

$container = new Container;

$container->addClass('Carbon', '\Carbon\Carbon');

$carbon = $container->get('Carbon');

var_dump($carbon->year) // 2018


두 메서드 모두 별칭을 첫 번째 매개변수로 사용합니다.

컨테이너 작동 방식



가장 기본적인 핵심에서 컨테이너는 개체 정의를 포함하는 매개 변수(배열)가 있는 개체입니다. 종속성( get('Carbon') )을 요청하면 컨테이너가 해당 배열에서 종속성을 찾습니다. 발견되면 개체가 빌드되고 반환됩니다. 그렇지 않은 경우 예외가 발생합니다. 특히 NotFoundException 예외입니다.

<?php 

[...]

class Container implements ContainerInterface
{

    /**
     * Definitions
     * @var array
     */
    private $definitions = [];

    [...]

    /**
     * Get
     *
     * Returns the passed alias.
     *
     * @param  string $id
     * @return mixed
     * @throws NotFoundException
     */
    public function get($id)
    {
        if (!$this->has($id)) {
            throw new NotFoundException(sprintf('%s is not defined.', $id));
        }

        $definition = $this->definitions[$id];
        $definition->addArguments($this->arguments);

        return $definition->build();
    }

    [...]

}


정의



정의는 컨테이너의 가장 중요한 측면입니다. 개체를 빌드하는 방법을 정의하며 해당 기능이 없으면 컨테이너를 사용할 수 없습니다. 각 정의는 DefinitionInterface 를 구현해야 합니다.

interface DefinitionInterface
{
    /**
     * Build
     *
     * @return object
     */
    public function build();
}


즉, 각 정의에는 개체를 반환하는 메서드build가 있어야 합니다.

각 정의는 AbstractDefinition 클래스를 확장해야 하지만 기술적으로 필수는 아닙니다.

abstract class AbstractDefinition implements DefinitionInterface
{
    /**
     * Arguments
     * @var array
     */
    public $arguments = [];

    /**
     * Add Arguments
     *
     * @param array $args
     */
    public function addArguments(array $args) : void
    {
        $this->arguments = $args;
    }

    /**
     * Has Arguments
     *
     * @return bool
     */
    public function hasArguments() : bool
    {
        return count($this->arguments) > 0;
    }
}



이 클래스는 여러 정의에서 사용되는 속성 및 메서드를 제공합니다.

class FactoryDefinition extends AbstractDefinition
{
    /**
     * Callback
     * @var Closure
     */
    private $callback;

    /**
     * Constructor
     *
     * @param Closure $callback
     */
    public function __construct(Closure $callback)
    {
        $this->callback = $callback;
    }

    /**
     * Build
     *
     * @return object
     */
    public function build()
    {
        return call_user_func_array($this->callback, $this->arguments);
    }
}




class ClassDefinition extends AbstractDefinition
{
    /**
     * Concrete
     * @var string
     */
    private $concrete;

    /**
     * Constructor
     *
     * @param string $concrete
     */
    public function __construct(string $concrete)
    {
        $this->concrete = $concrete;
    }

    /**
     * Build
     *
     * @return object
     */
    public function build()
    {
        if ($this->hasArguments()) {
            $reflection = new ReflectionClass($this->concrete);

            return $reflection->newInstanceArgs($this->arguments);
        }

        return new $this->concrete;
    }
}



보시다시피 두 유형의 정의 모두 개체를 빌드하는 방법을 설명합니다.

인수



위의 코드에서 개체를 빌드할 때 인수를 사용할 수 있다는 것을 눈치챘을 것입니다. 예를 들어 Carbon 인스턴스를 구축할 때 날짜와 시간을 전달할 수 있다고 가정해 보겠습니다. 다음과 같이 표시됩니다.

$container->withArguments(['2010-05-16 22:40:10'])->get('Carbon');


할 일이 남았다



컨테이너에 대해 수행해야 할 작업이 아직 많이 남아 있지만 현재 상태에 매우 만족합니다. 남아 있는 가장 시급한 기능은 SetterDefinition 및 이와 관련된 메서드 호출 기능을 구현하는 것입니다. 또한 의존성을 자동으로 주입하기 위해 리플렉션을 사용할 것입니다. 그것이 어떻게 보일지 완전히 확신할 수는 없지만 시작하게 되어 기쁩니다.

피드백



당신의 의견을 듣고 싶습니다. 제안이나 다른 것이 있으면 내 .

마지막으로 제 뉴스레터를 꼭 확인하세요! 매주 저는 업데이트, 훌륭한 링크, 팁과 요령, 기타 비개발자 무작위성으로 가득 찬 훌륭한 이메일을 보내드립니다. 관심이 있으시면 다음link을 따라 가입할 수 있습니다.

좋은 웹페이지 즐겨찾기