zoukankan      html  css  js  c++  java
  • laravel-容器

            一.作用:容器的作用主要是为了生成,存储实例,解决各种依赖关系

       二.例子:如下所示, test需要注入参数$param 并依赖类rely

    <?php
    require 'vendor/autoload.php';
    
    use IlluminateContainerContainer;
    $container = new Container();
    
    class test {
        public $param, $rely;
        public function __construct($param = 'default', rely $rely) {
            $this->param = $param;
            $this->rely = $rely;
        }
        
        public function run($runParam) {
            echo $runParam . PHP_EOL;
        }
    }
    class rely {}

      三.调用示例(部分方法是为了实现一些接口类)

      (1)make  生成一个实例并自动解决依赖关系

    //按默认参数生成test
    echo $container->make('test')->param . PHP_EOL;
    
    //自定义参数
    echo $container->make('test', ['param' => 1])->param . PHP_EOL;

      (2)when 上下文绑定

    //绑定参数
    $container->when(['test'])->needs('$param')->give(2);
    echo $container->make('test')->param . PHP_EOL;
    
    //绑定实例
    $container->when('test')->needs('rely')->give(function ($app) {
        $rely = new rely();
        $rely->tag = 'by when';
        return $rely;
    });
    
    echo $container->make('test')->rely->tag . PHP_EOL;

      (3)自定义方式绑定

    $container->bind('test', function($app) {
        return new test('by bind', new rely);
    });
    echo $container->make('test')->param . PHP_EOL;

      ps:关于这几种参数注入的方式  优先级排序 make带参数 > 上下文绑定  > 默认值

      (4)bind时$shared设置为true为单例模式(前提是没有传参或者设置上下文)

    //bind时$shared设置为true
    $container->bind('test', function ($app) {
        return new test('param', new rely);
    }, true);
    
    //修改实例的param, 再去拿是修改后的值
    $container->make('test')->param = 1;
    echo $container->make('test')->param . PHP_EOL;
    
    //所有的单例缓存在instances中
    call_user_func(Closure::bind(function () use ($container) {
        print_r($container->instances);
    }, null, Container::class));

      (5)bound 是否被bind过

    echo $container->bound('test') . PHP_EOL;
    $container->bind('test');
    echo $container->bound('test') . PHP_EOL;

      (6)has 同bound

    echo $container->has('test') . PHP_EOL;
    $container->bind('test');
    echo $container->has('test') . PHP_EOL;

      (7)resolved 是否被make过

    echo $container->resolved('test') . PHP_EOL;
    $container->make('test');
    echo $container->resolved('test') . PHP_EOL;

      (8)isShared 绑定时候$shared是否设置为true

    $container->bind('test');
    echo $container->isShared('test') . PHP_EOL;
    $container->bind('test', function ($app) {
        return new test;
    }, true);
    echo $container->isShared('test') . PHP_EOL;

      (9)alias 设置别名;isAlias 是否为别名

    echo $container->isAlias('test2') . PHP_EOL;
    $container->alias('test', 'test2');
    echo $container->isAlias('test2') . PHP_EOL;
    echo $container->make('test2')->param;

      (10)bindMethod 方法绑定

    $container->bindMethod('testMethod', function ($instance, $app) {
        $app->bind('callBackGivenObj', function($app) use ($instance){
            return $instance;
        });
    });
    
    //hasMethodBinding 是否绑定了方法
    echo $container->hasMethodBinding('testMethod');
    
    //callMethodBinding 执行之前绑定的方法(绑定了一个名为callBackGivenObj的实例)
    $container->callMethodBinding('testMethod', new test('callback', new rely));
    echo $container->make('callBackGivenObj')->param;

      (11)addContextualBinding 增加上下文绑定关系  同when

    $container->addContextualBinding('test', '$param', 1);
    echo $container->make('test')->param;
    $container->addContextualBinding('test', 'rely', function($app) {
        $rely = new rely();
        $rely->tag = 'by addContextualBinding';
        return $rely;
    });
    echo $container->make('test')->rely->tag;

      (12)bindIf  如果已经被bind过就不会执行

    $container->bind('test', function ($app) {
        return new test('bind', new rely);
    });
    
    $container->bindIf('test', function ($app) {
        return new test('bindIf', new rely);
    });
    
    echo $container->make('test')->param;

      (13)singleton 单例模式绑定  同$this->bind($abstract, $concrete, true)

    $container->singleton('test');
    $container->make('test')->param = 'change';
    echo $container->make('test')->param;

      (14)extend 类似装饰着模式 生成实例后会挨个执行extend,存在instances或make过会触发rebound

    $container->extend('test', function($instances, $app) {
        $instances->param = 10;
        return $instances;
    });
    
    $container->extend('test', function($instances, $app) {
        $instances->param += 10;
        return $instances;
    });
    
    echo $container->make('test')->param;

      (15)instance 直接注入实例缓存  make时直接返回缓存 如果之前bind过会触发rebound

    $rely = new rely();
    $rely->tag = 'instance';
    $container->instance('test', new test('instance', $rely));
    echo $container->make('test')->param . PHP_EOL;
    
    //有参数会重新生成实例
    echo $container->make('test', ['param' => 'other instance cause param'])->param . PHP_EOL;
    
    //但上下文绑定不好使了 走的是单例缓存
    $container->when('test')->needs('$param')->give('other instance cause when');
    echo $container->make('test')->param;

      (16)tag 打包 批make

    $container->bind('test1', function($app) {
        return new test('test1', new rely);
    });
    $container->bind('test2', function($app) {
        return new test('test2', new rely);
    });
    
    $container->tag(['test1', 'test2'], 'testTag');
    $testTags = $container->tagged('testTag');
    echo count($testTags) . PHP_EOL;
    foreach ($testTags as $testObj) {
        echo $testObj->param . PHP_EOL;
    }

      (17)rebinding 监听到绑定的实例发生更改时执行  可以设置多个 一般有三种情况  重新bind 或者加extend 或者设置instance

    $container->bind('test', function ($app) {
        return new test('test', new rely);
    });
    
    //$oldInstance 为以当前绑定方式生成的实例
    $oldInstance = $container->rebinding('test', function ($app, $instance) {
        echo ' to ' . $instance->param . PHP_EOL;
    });
    
    echo 'change ' . $oldInstance->param;
    
    //重新绑定  触发rebind
    $container->bind('test', function ($app) {
        return new test('test2', new rely);
    });

      (18)refresh  同rebinding 只是把匿名函数的方式改成 class->metohd的方式

    class handler {
        public function deal($instance) {
            echo ' to ' . $instance->param . PHP_EOL;
        }
    }
    
    $container->bind('test', function ($app) {
        return new test('test', new rely);
    });
    
    $oldInstance = $container->refresh('test', new handler, 'deal');
    echo 'change ' . $oldInstance->param;
    $container->bind('test', function ($app) {
        return new test('test2', new rely);
    });

      (18)call 执行class->method  第二个参数为带入的参数

    $container->call('test@run', ['runParam' => 'byCall1']);
    $container->call(['test', 'run'], ['runParam' => 'byCall2']);
    $container->call('test', ['runParam' => 'byCall3'], 'run');
    
    //匿名函数方式  test会自动make
    $container->call(function (test $test, $otherParam) {
        $test->run($otherParam);
    }, ['otherParam' => 'byCall4']);
    
    //如果之前被绑定过不会执行test->run 而会执行被绑定的方法
    $container->bindMethod('test@run', function ($instance, $app) {
        echo 'by bindMethod' . PHP_EOL;
    });
    
    $container->call(['test', 'run'], ['runParam' => 'byCall5']);

      (19)wrap  打包一个方法

    $closuer = $container->wrap(function(test $test, $param) {
        echo $param;
    }, ['param' => 'wrap']);
    
    call_user_func($closuer);

      (20)factory 打包一个make方法

    $closuer = $container->factory('test');
    $testInstance = call_user_func($closuer);
    echo $testInstance->param;

      (21)makeWith 同make

      (22)get 同make(带不了参数)

      (23)build 可以当成纯净版的make(make的下游) 没有那么多乱七八糟的能力(alias, ContextualConcrete, instances, extender等) 只是单纯的解决依赖

      (24)resolving  resolve的后置钩子

    $container->resolving('test', function ($instance, $app) {
        echo 'make test done' . PHP_EOL;
    });
    
    $container->make('test');
    
    //单例模式只会在第一次促发
    $container->bind('test', 'test', true);
    $container->make('test');
    $container->make('test');
    //全局加钩子
    $container->resolving(function ($instance, $app) {
        echo 'done' . PHP_EOL;
    });
    
    //这里会打印两次done  一次是构建test的时候  一次是构建rely的时候(test的依赖)
    $container->make('test');

      (25)fireResolvingCallbacks 用法同resolving 执行顺序在resolving钩子之后

      (26)getBindings 获取bind信息

      (27)forgetExtenders 去除之前设置的扩展

    $container->extend('test', function($instances, $app) {
        $instances->param = 10;
        return $instances;
    });
    echo $container->make('test')->param . PHP_EOL;
    $container->forgetExtenders('test');
    echo $container->make('test')->param . PHP_EOL;

      (28)forgetInstance 去除单例

    $container->instance('test', new test('instance', new rely));
    echo $container->make('test')->param . PHP_EOL;
    $container->forgetInstance('test');
    echo $container->make('test')->param . PHP_EOL;

      (29)forgetInstances 去除所有单例

    $container->instance('test', new test('instance', new rely));
    echo $container->make('test')->param . PHP_EOL;
    $container->forgetInstances();
    echo $container->make('test')->param . PHP_EOL;

      (30)flush 全清空  清空内容如下

    $this->aliases = [];
    $this->resolved = [];
    $this->bindings = [];
    $this->instances = [];
    $this->abstractAliases = [];

      (31)getInstance  单例模式  返回容器本身

      (32)setInstance  设置返回getInstance的实例

      (33)offsetExists 同 bound

      (34)offsetGet 同 make

      (35)offsetSet 同bind  用法有些差异 如下

    public function offsetSet($key, $value)
    {
        $this->bind($key, $value instanceof Closure ? $value : function () use ($value) {
            return $value;
        });
    }

      (36)offsetUnset 如下

    public function offsetUnset($key)
    {
        unset($this->bindings[$key], $this->instances[$key], $this->resolved[$key]);
    }
  • 相关阅读:
    [转载]PHP中PSR-[0-4]规范
    Git忽略规则及.gitignore规则不生效的解决办法
    nginx配置tp5的pathinfo模式并隐藏后台入口文件
    php过滤&nbsp;字符
    使用ajax的post方式下载excel
    scws简单中文分词
    php的api及登录的权限验证
    对钩子的理解
    基于角色的权限控制
    微信开发之SVN提交代码与FTP同步到apache的根目录
  • 原文地址:https://www.cnblogs.com/wangjianheng/p/14057716.html
Copyright © 2011-2022 走看看