Closure之bindTo 简述 laravel源码分析 基础

43 篇文章 0 订阅
11 篇文章 0 订阅

导语

类似于go语言的方法的接收者,js中的apply,bind,call改变函数对象的调用者,以及其它语言的上下文context。php也可以给函数指定this,即通俗意义上的改变其宿主。而bindTo就是这一作用,(注:php中函数都是closure实例,将函数绑定到实例对象上的用bindTo方法)

例1:

使用bindTo 给目标类添加执行初始条件(注册)

class A{
    private $name='Hi';

    public function test()
    {
        echo 'name: '.$this->name, 'age: '.$this->age,"\n";
    }

}

// 1.准备匿名函数
$fn = function(){
    return $this->age = 18;
};

// 2.准备被操作的实例
$o = new A;

// 3.将闭包绑定到实例
$new_fn = $fn->bindTo($o,$o);

// 4.执行闭包匿名函数,给对象实例动态添加属性(作初始化工作)
$new_fn();

// 执行实例方法
$o->test();


小结:很显然,如果缺少闭包添加某些生产脚本,实例的相关方法执行难以为继    。实质:将注册(register)与启动(boot)分离。注册仅仅只是一个映射,描述某种关系。而启动则是初始化。故通常顺序是 注册->启动->使用。

例2:

需求:给目标类动态添加方法

// 
// 使用trait

trait MetaTrait{
    
    private $methods = array();

    // 对外接口
    public function addMethod($methodName, $methodCallable)
    {
        if (!is_callable($methodCallable)) {
            throw new InvalidArgumentException('第二个参数必须是一个可调用类型');
        }
        // 新的闭包绑定到当前对象(生产脚本,即改变this的指向,其方法可被动态访问,指定类型范围),
        $this->methods[$methodName] = Closure::bind($methodCallable, $this, get_class());
    }

    public function __call($methodName, array $args)
    {
        //调用绑定的闭包
        if (isset($this->methods[$methodName])) {
            return call_user_func_array($this->methods[$methodName], $args);
        }
        throw RunTimeException('没有该方法');
    }

    
}

// 实现 
class Foo{
    use MetaTrait;

    private $dayOfWeek = 'Thursday';
}

//1.获取实例
$test = new Foo();

// 绑定方法
$test->addMethod('when', function () {
    return $this->dayOfWeek;
});

//调用对象方法
echo $test->when();        //Thursday


小结:
1.依赖于被添加的类实例 类似于装饰器设计
2.绑定的this指向,Closure 形成新绑定闭包
3.闭包调用是函数式

 

laravel集合类源码分析

在类的调用时,比如集合

use Illuminate\Support\Str;

Collection::macro('toUpper', function () {
    return $this->map(function ($value) {
        return Str::upper($value);
    });
});

$collection = collect(['first', 'second']);

$upper = $collection->toUpper();

// ['FIRST', 'SECOND']

::macro 宏添加指令 给集合类某个属性数组添加闭包,在后续实例调用->toUpper() ,会优先调用__call(内部检查该闭包数组)相应闭包方法。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值