PHP 의존 주입 컨테이너를 만듭니다.
100달러짜리 신용카드를 받다
PHP 의존 주입 컨테이너를 만들고 Laravel에서 의존 및 매개변수 부팅 컨트롤러 및 방법을 학습합니다.
우리는 Laravel를 사용하여 프로그램을 구축하고 있지만, 우리들 중 많은 사람들이 Laravel 의존항과 파라미터 시작 컨트롤러와 방법을 어떻게 사용하는지 모른다.
우리가 선포한 노선은 다음과 같다.
Route::get('hello', 'TestController@index')
우리의 디렉터는 다음과 같습니다.
namespace App\Http\Controllers\Test;
class TestController extends Controller
{
private $requests;
public function __construct( Request $request)
{
$this->requests = $request;
}
/**
* Show the application dashboard.
*/
public function index(TestModel $testModel)
{
return $testModel->get();
}
}
또는 이와 같은 노선:
Route::get('hello', 'TestController')
다음과 같은 컨트롤러도 있습니다.
namespace App\Http\Controllers\Test;
class TestController extends Controller
{
private $requests;
public function __construct( Request $request)
{
$this->requests = $request;
}
/**
* Show the application dashboard.
*/
public function __invoke(TestModel $testModel)
{
return $testModel->get();
}
}
문제는 다음과 같습니다.
1.1 Laravel은 어떻게 구조의 의존 관계와 주입을 검측합니까?
1.2와 Laravel은 어떻게 구조의 의존항을 사용하여 클래스를 초기화하고 그 의존항과 파라미터를 사용하여'인덱스'방법을 호출합니까?
2.1 방법명은 전달하지 않지만 Laravel은 기본값으로 호출 방법을 어떻게 감지합니까?
주입 용기에 의존해서 앞의 문제를 이해하도록 하자.
왜 우리가 알아야 합니까?
Route::get('hello', 'TestController@index')
namespace App\Http\Controllers\Test;
class TestController extends Controller
{
private $requests;
public function __construct( Request $request)
{
$this->requests = $request;
}
/**
* Show the application dashboard.
*/
public function index(TestModel $testModel)
{
return $testModel->get();
}
}
Route::get('hello', 'TestController')
namespace App\Http\Controllers\Test;
class TestController extends Controller
{
private $requests;
public function __construct( Request $request)
{
$this->requests = $request;
}
/**
* Show the application dashboard.
*/
public function __invoke(TestModel $testModel)
{
return $testModel->get();
}
}
PHP 반사 우리 시작하자.
우리들의 발걸음
1. 클래스를 만듭니다.
class DependencyInjectionContainer
{
/**
* The container's instance.
*
* @var static
*/
protected static $instance;
/**
* the class name with namespace
*
* @var string
*/
protected $callbackClass;
/**
* the method name of provided class
*
* @var string
*/
protected $callbackMethod;
/**
* method separator of a class. when pass class and method as string
*/
protected $methodSeparator = '@';
/**
* namespace for class. when pass class and method as string
*
* @var string
*/
protected $namespace = "App\\controller\\";
/**
* get Singleton instance of the class
*
* @return static
*/
public static function instance()
{
}
/**
* @param $callable -- string class and method name with separator @
* @param array $parameters
*/
public function call($callable, $parameters = [])
{
}
/**
* separate class and method name
* @param $callback
*/
private function resolveCallback($callback)
{
}
/**
* instantiate class with dependency and return class instance
* @param $class - class name
* @param $parameters (optional) -- parameters as array . If constructor need any parameter
*/
public function make($class, $parameters = [])
{
}
}
클래스를 초기화하고 구조 함수에 의존하는 항목과 파라미터를 주입하는 방법 (make) 만들기
PHP 를 사용하겠습니다.이 섹션에서는 PHPPHP Reflection 개체를 사용합니다.PHPReflactionClass에는 여러 가지 방법이 있습니다.
이 절에서, 우리는 클래스 실례를 만들어야 한다.
만약 우리가 어떤 종류의 실례를 만들면, 모든 의존항과 파라미터를 전달하고 주입해야 한다는 것을 우리는 알고 있다.
PHPReflactionClass를 사용하려면 모든 종속성을 테스트해야 합니다.
public function make($class, $parameters = [])
{
$classReflection = new ReflectionClass($class);
$constructorParams = $classReflection->getConstructor()->getParameters();
}
위 코드에서 구조 함수의 모든 매개 변수를 $constructorParams 변수로 수집합니다.그리고 $constructorParams를 사용하여 매개 변수와 의존 관계를 순환하고 검사해야 합니다.
public function make($class, $parameters = [])
{
$classReflection = new ReflectionClass($class);
$constructorParams = $classReflection->getConstructor()->getParameters();
$dependencies = [];
/*
* loop with constructor parameters or dependency
*/
foreach ($constructorParams as $constructorParam) {
$type = $constructorParam->getType();
if ($type && $type instanceof ReflectionNamedType) {
echo "It is a class and we need to instantiate the class and pass to constructor"
} else {
echo "This is a normal parameter and We need to find parameter value from $parameters . If not found value then needs to check if this parameter is optional or not. If not optional then through error"
}
}
}
주요 사항:public function make($class, $parameters = [])
{
$classReflection = new ReflectionClass($class);
$constructorParams = $classReflection->getConstructor()->getParameters();
$dependencies = [];
/*
* loop with constructor parameters or dependency
*/
foreach ($constructorParams as $constructorParam) {
$type = $constructorParam->getType();
if ($type && $type instanceof ReflectionNamedType) {
// make instance of this class :
$paramInstance = $constructorParam->getClass()->newInstance()
// push to $dependencies array
array_push($dependencies, $paramInstance);
} else {
$name = $constructorParam->getName(); // get the name of param
// check this param value exist in $parameters
if (array_key_exists($name, $parameters)) { // if exist
// push value to $dependencies sequencially
array_push($dependencies, $parameters[$name]);
} else { // if not exist
if (!$constructorParam->isOptional()) { // check if not optional
throw new Exception("Can not resolve parameters");
}
}
}
}
// finally pass dependancy and param to class instance
return $classReflection->newInstance(...$dependencies);
}
나는 코드로 모든 것을 설명한다.좋아...우리는 이미 클래스의 의존항 주입 용기를 완성했다
단일 인스턴스를 만듭니다.
public static function instance()
{
if (is_null(static::$instance)) {
static::$instance = new static;
}
return static::$instance;
}
기본용법 $container = DependencyInjectionContainer::instance();
클래스 정의class MyClass
{
private $dependency;
public function __construct(AnotherClass $dependency)
{
$this->dependency = $dependency;
}
}
new MyClass
대신 용기를 사용하는 make()
방법:$instance = $container->make(MyClass::class);
컨테이너가 의존 항목을 자동으로 실례화하므로 이 기능은 다음과 같습니다.$instance = new MyClass(new AnotherClass());
인스턴스다음은 메일 프로그램 기능과 사용자 등록을 분리하는 ReflactionClass 기반의 보다 실용적인 예입니다.
class Mailer
{
public function mail($recipient, $content)
{
// Send an email to the recipient
// ...
}
}
class UserManager
{
private $mailer;
public function __construct(Mailer $mailer)
{
$this->mailer = $mailer;
}
public function register($email, $password)
{
// Create the user account
}
}
$container = DependencyInjectionContainer::instance();
$userManager = $container->make(UserManager::class);
$userManager->register('[email protected]', 'MySuperSecurePassword!');
PHP-DI 설명서 3. 클래스와 방법을 추출하고 이 방법의 의존항과 파라미터를 주입하는 방법(호출)을 만듭니다.
이 섹션에서는 Laravel이 컨트롤러와 방법을 어떻게 해석하고 의존항/파라미터를 사용하여 시작하는지 알아보겠습니다.
층계
make()
기능클래스에는 클래스 이름과 방법 이름을 구분하는 구분자로 $methodSeparator의 속성이 있습니다.
private function resolveCallback($callable)
{
//separate class and method
$segments = explode($this->methodSeparator, $callable);
// set class name with namespace
$this->callbackClass = $this->namespace.$segments[0];
// set method name . if method name not provided then default method __invoke
$this->callbackMethod = isset($segments[1]) ? $segments[1] : '__invoke';
}
2. 검측 방법의 관련성/파라미터와 호출 방법 public function call($callable, $parameters = [])
{
// set class name with namespace and method name
$this->resolveCallback($callable);
// initiate ReflectionMethod with class and method
$methodReflection = new ReflectionMethod($this->callbackClass, $this->callbackMethod);
// get all dependencies/parameters
$methodParams = $methodReflection->getParameters();
$dependencies = [];
// loop with dependencies/parameters
foreach ($methodParams as $param) {
$type = $param->getType(); // check type
if ($type && $type instanceof ReflectionNamedType) { /// if parameter is a class
$name = $param->getClass()->newInstance(); // create insrance
array_push($dependencies, $name); // push to $dependencies array
} else { /// Normal parameter
$name = $param->getName();
if (array_key_exists($name, $parameters)) { // check exist in $parameters
array_push($dependencies, $parameters[$name]); // push to $dependencies array
} else { // if not exist
if (!$param->isOptional()) { // check if not optional
throw new Exception("Can not resolve parameters");
}
}
}
}
// make class instance
$initClass = $this->make($this->callbackClass, $parameters);
// call method with $dependencies/parameters
return $methodReflection->invoke($initClass, ...$dependencies);
}
이제 Laravel에서 호출 함수의 매개 변수를 수집하는 방법에 대한 질문이 있습니다.동적 매개변수를 사용하여 라우트를 선언할 때, 예를 들면 다음과 같습니다.
Route::get('hello/{name}', 'TestController@index')
Laravel 라우팅 시스템은 모든 매개변수를 수집하여 호출 기능에 전달합니다.$parameters = ["name" => "AL EMRAN" ];
$container->cal("TestController@index", $parameters)
사용법$container->call('TestController@index');
$container->call('TestController@show', ['id' => 4]);
$container->call('TestController');
$container->call('TestController', ['id' => 4]);
혹은예.
class TestController
{
protected $company;
public function __construct(Company $company)
{
$this->company = $company ;
}
/**
* @param Request $request
*/
public function index(Request $request){
$company = $company->get();
return view('admin.company', compact('company'));
}
}
다음과 같은 이점을 누릴 수 있습니다. $instance = DependencyInjectionContainer::instance();
$instance->namespace = "App\\Http\Controllers\\Admin\\"; // change namespace
$class = $instance->make(CompanyController::class); // make class instance
$instance->call(["CompanyController", 'index']); // call method
$instance->call([$class, 'index']); // or--call method
패키지 설치
패키지Github 링크
composer require emrancu/dependency-injection-container
여기 있다
설교자
Laravel 의존 주입 용기는 매우 방대하며, 그것의 루트 시스템도 마찬가지다.내가 이 부류를 만든 것은 단지 이해하기 위해서이다.
첫 번째 기사입니다. 귀하의 의견을 평가하거나 "
"로 이메일을 보내 주십시오.
아이디어[email protected]
Here
Reference
이 문제에 관하여(PHP 의존 주입 컨테이너를 만듭니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/emrancu/let-s-create-php-dependency-injection-container-24lm
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
composer require emrancu/dependency-injection-container
Reference
이 문제에 관하여(PHP 의존 주입 컨테이너를 만듭니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/emrancu/let-s-create-php-dependency-injection-container-24lm텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)