laravel服务容器

 

laravel框架底层解析

本文参考陈昊《Laravel框架关键技术解析》,搭建一个属于自己的简化版服务容器。
其中涉及到反射、自动加载,还是需要去了解一下。

laravel服务容器

  1. 建立项目空文件夹(如 mylaravel)

  2. 添加composer.json,执行composer install

{
    "name": "laravel/laravel",
    "description": "The Laravel Framework.",
    "keywords": ["framework", "laravel"], "license": "MIT", "type": "project", "autoload": { "classmap": [ ], "psr-4": { "App\\": "app/" } } } 

目的是为了学习、利用composer的自动加载。

  1. 文件路径如下所示

  • mylaravel

    • app

      • Traveller

        • Traveller.php

      • Visit

        • Leg.php

        • Visit.php

      • Container.php

      • Index.php

    • vendor

    • composer.json

  1. 简化版Container.php

<?php
namespace App;

Class Container { protected $bindings = []; /** * 绑定接口和生成相应实例的回调函数 * @param $abstract 服务名称 * @param null $concreate 回调函数或名称 * @param bool $shared 是否为单例 * */ public function bind($abstract, $concrete = null, $shared = false) { if ( ! $concrete instanceof \Closure) { // 如果提供的参数不是回调函数,则产生默认的回调函数 $concrete = $this->getClosure($abstract, $concrete); } $this->bindings[$abstract] = compact('concrete', 'shared'); } //默认的回调函数 protected function getClosure($abstract, $concrete) { //生成实例的回调函数, $c一般为ioc容器对象 return function($c) use ($abstract, $concrete) { $method = ($abstract == $concrete) ? 'build' : 'make'; return $c->$method($concrete); }; } //生成实例对象,首先解决接口和要实例化类之间的依赖 public function make($abstract) { $concrete = $this->getConcrete($abstract); if ($this->isBuildable($concrete, $abstract)) { $object = $this->build($concrete); } else { $object = $this->make($concrete); } return $object; } protected function isBuildable($concrete, $abstract) { return $concrete === $abstract || $concrete instanceof \Closure; } //获取绑定的回调函数 protected function getConcrete($abstract) { if ( ! isset($this->bindings[$abstract])) { return $abstract; } return $this->bindings[$abstract]['concrete']; } //实例化对象 public function build($concrete) { if ($concrete instanceof \Closure) { return $concrete($this); } $reflector = new \ReflectionClass($concrete); if ( ! $reflector->isInstantiable()) { echo $message = "Target [$concrete] is not instantiable."; } $constructor = $reflector->getConstructor(); if (is_null($constructor)) { return new $concrete; } $dependencies = $constructor->getParameters(); $instances = $this->getDependencies($dependencies); return $reflector->newInstanceArgs($instances); } protected function getDependencies($parameters) { $dependencies = []; foreach ($parameters as $parameter) { $denpendency = $parameter->getClass(); if (is_null($denpendency)) { $dependencies[] = NULL; } else { $dependencies[] = $this->resolveClass($parameter); } } return (array) $dependencies; } protected function resolveClass(\ReflectionParameter $parameter) { return $this->make($parameter->getClass()->name); } }

Visit.php接口

<?php
namespace App\Visit;

interface Visit { public function go(); }

Leg.php接口的一种实现

<?php
namespace App\Visit;

Class Leg implements Visit { public function go() { echo "walk to tibet!"; } }

Traveller.php相当于Controller下的方法

<?php
namespace App\Traveller;

use App\Visit\Visit; Class Traveller { protected $trafficTool; //Visit是抽象类,index中将leg注入到了容器,取代了Visit public function __construct(Visit $visit) { $this->trafficTool = $visit; } public function visitTibet() { $this->trafficTool->go(); } }

Index.php

<?php 
namespace App;

//调用composer的自动加载
require '../vendor/autoload.php'; Class Index { public function index() { //实例化ioc容器 $app = new Container(); //容器填充 $app->bind('App\Visit\Visit', '\App\Visit\Leg'); $app->bind('Traveller', '\App\Traveller\Traveller'); //通过容器实现依赖注入,完成类的实例化 $tra = $app->make("\App\Traveller\Traveller"); $tra->visitTibet(); } } $b = new Index; $b->index();

猜你喜欢

转载自www.cnblogs.com/php-linux/p/10658209.html
今日推荐