百度百科定义:宏在计算机科学中是批处理的术语。一般来说,宏是一种规则或模式,或语法替换,用于描述如何将特定的输入(通常是字符串)按照预定义的规则转换为相应的输出(通常是字符串)。这种替换发生在预编译时,称为宏扩展。第一次接触宏是在大学上计算机基础课时老师讲office的时候。当时老师介绍宏操作的时候,我也没怎么注意。才想起来这个操作很强大,可以让日常工作变得更轻松。今天我们讲讲Laravel中的宏操作首先完整的源代码getMethods(ReflectionMethod::IS_PUBLIC|ReflectionMethod::IS_PROTECTED);foreach($methodsas$method){$method->setAccessible(true);static::macro($method->name,$method->invoke($mix在));}}/***检查宏是否已注册。**@paramstring$name*@returnbool*/publicstaticfunctionhasMacro($name){returnisset(static::$macros[$name]);}}/***动态处理对类的调用。**@paramstring$method*@paramarray$parameters*@returnmixed**@throws\BadMethodCallException*/publicstaticfunction__callStatic($method,$parameters){if(!static::hasMacro($method)){thrownewBadMethodCallException("方法{$method}不存在。");}if(static::$macros[$method]instanceofClosure){returncall_user_func_array(Closure::bind(static::$macros[$method],null,static::class),$parameters);}返回call_user_func_array(static::$macros[$method],$parameters);}/***动态处理对类的调用。**@paramstring$方法d*@paramarray$parameters*@returnmixed**@throws\BadMethodCallException*/publicfunction__call($method,$parameters){if(!static::hasMacro($method)){thrownewBadMethodCallException("方法{$方法}不存在。");}$macro=static::$macros[$method];如果($macroinstanceofClosure){returncall_user_func_array($macro->bindTo($this,static::class),$parameters);}返回call_user_func_array($macro,$parameters);}}Macroable::macro方法publicstaticfunctionmacro($name,$macro){static::$macros[$name]=$macro;}很简单根据参数的注释,$macro可以传一个闭包或者一个东西。之所以可以传递对象,得益于PHP中的魔法方法classFather{//通过加入魔法方法**__invoke**,我们可以传递对象作为闭包公共函数__invoke(){echo__CLASS__;}}classChild{use\Illuminate\Support\Traits\Macroable;}//添加宏指令后,我们可以调用Child对象中不存在的方法Child::macro('show',newFather);//输出:Father(newChild)->show();Macroable::mixinmethod该方法是将一个对象的方法的返回结果注入到原对象中publicstaticfunctionmixin($mixin){//通过反射获取该对象中所有的public和protected方法$methods=(newReflectionClass($mixin))->getMethods(ReflectionMethod::IS_PUBLIC|ReflectionMethod::IS_PROTECTED);foreach($methodsas$method){//设置方法是可访问的,因为它是受保护的,不能被外部调用$method->setAccessible(true);//调用宏方法批量创建宏static::macro($method->name,$method->invoke($mixin));}}//实际使用classFather{publicfunctionsay(){returnfunction(){echo'say';};}publicfunctionshow(){returnfunction(){echo'show';};}protectedfunctioneat(){返回函数(){echo'吃';};}}classChild{use\Illuminate\Support\Traits\Macroable;}//批量绑定宏指令Child::mixin(newFather);$child=newChild;//输出:say$child->say();//输出:show$child->show();//输出:eat$child->eat();从上面的代码可以看出,mixin可以绑定一个类的方法,在宏类中需要注意的是,该方法必须返回一个闭包类型。Macroable::hasMacro方法publicstaticfunctionhasMacro($name){returnisset(static::$macros[$name]);}这个方法比较简单,一点也不复杂,判断是否有宏指令即可。通常在使用宏指令前进行判断。Macroable::__call和Macroable::__callStatic方法正是因为这两个方法,我们才可以进行宏操作。两种方法除了执行方式不同外,代码都差不多。先说__callpublicfunction__call($method,$parameters){//如果这条宏指令不存在,直接抛出异常if(!static::hasMacro($method)){thrownewBadMethodCallException("Method{$方法}不存在。");}//获取存储的宏指令$macro=static::$macros[$method];//闭包做一点特殊处理if($macroinstanceofClosure){returncall_user_func_array($macro->bindTo($this,static::class),$parameters);}//不是闭包,比如对象,直接通过这个方法运行,但是要确保对象有`__invoke`方法returncall_user_func_array($macro,$parameters);}classChild{use\Illuminate\Support\性状\可宏观化;protected$name='father';}//对于闭包的特殊处理,只需要绑定$this即可,如Child::macro('show',function(){echo$this->name;});//输出:father(newChild)->show();当我们在上述操作中绑定宏时,在闭包中Child的属性可以通过$this调用,因为我们在__call方法中使用了Closure::bindTo方法。官网对Closure::bindTo的解释:复制当前闭包对象,绑定指定的$this对象和类作用域。在Laravel中的类中添加宏指令Laravel中的许多类都使用宏特性,例如Illuminate\Filesystem\Filesystem::class。我们想给这个类加一个方法,但是里面的代码是不会动的。我们只需要在App\Providers\AppServiceProvider::register方法中添加宏指令(也可以新建一个服务提供者进行特殊处理),然后添加一个测试路由,测试我们新添加的方法然后打开浏览器运行,你会发现我们的代码可以正常运行并输出原来的地址
