この記事では、主に Laravel での Macroable マクロの使用法を紹介します。これには特定の参考値があります。今、あなたに共有します。必要な友人は、
Baidu Encyclopedia の定義を参照してください:
コンピュータ内のマクロサイエンスはバッチ処理を表す用語です。一般に、マクロとは、事前定義されたルールに従って、特定の入力 (通常は文字列) が対応する出力 (通常は文字列) にどのように変換されるかを説明するために使用されるルール、パターン、または構文置換です。この置換はプリコンパイル時に行われ、マクロ展開と呼ばれます。
私が初めてマクロに触れたのは、大学でコンピューターの基礎コースを受講していたとき、先生が office について話したときでした。当時、先生はマクロ操作を導入したときはあまり注目せず、ただこの操作が非常に強力で、日々の作業が楽になるということだけを覚えていました。
今日は Laravel でのマクロ操作について話します
<?php namespace Illuminate\Support\Traits; use Closure; use ReflectionClass; use ReflectionMethod; use BadMethodCallException; trait Macroable { /** * The registered string macros. * * @var array */ protected static $macros = []; /** * Register a custom macro. * * @param string $name * @param object|callable $macro * * @return void */ public static function macro($name, $macro) { static::$macros[$name] = $macro; } /** * Mix another object into the class. * * @param object $mixin * @return void */ public static function mixin($mixin) { $methods = (new ReflectionClass($mixin))->getMethods( ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED ); foreach ($methods as $method) { $method->setAccessible(true); static::macro($method->name, $method->invoke($mixin)); } } /** * Checks if macro is registered. * * @param string $name * @return bool */ public static function hasMacro($name) { return isset(static::$macros[$name]); } /** * Dynamically handle calls to the class. * * @param string $method * @param array $parameters * @return mixed * * @throws \BadMethodCallException */ public static function __callStatic($method, $parameters) { if (! static::hasMacro($method)) { throw new BadMethodCallException("Method {$method} does not exist."); } if (static::$macros[$method] instanceof Closure) { return call_user_func_array(Closure::bind(static::$macros[$method], null, static::class), $parameters); } return call_user_func_array(static::$macros[$method], $parameters); } /** * Dynamically handle calls to the class. * * @param string $method * @param array $parameters * @return mixed * * @throws \BadMethodCallException */ public function __call($method, $parameters) { if (! static::hasMacro($method)) { throw new BadMethodCallException("Method {$method} does not exist."); } $macro = static::$macros[$method]; if ($macro instanceof Closure) { return call_user_func_array($macro->bindTo($this, static::class), $parameters); } return call_user_func_array($macro, $parameters); } }
Macroable::macro
Method
public static function macro($name, $macro) { static::$macros[$name] = $macro; }
パラメータのコメントによると、非常に単純なコード $macro
クロージャまたはオブジェクトを渡すことができます。オブジェクトを渡すことができる理由は、PHP
class Father { // 通过增加魔术方法**__invoke**我们就可以把对象当做闭包来使用了。 public function __invoke() { echo __CLASS__; } } class Child { use \Illuminate\Support\Traits\Macroable; } // 增加了宏指令之后,我们就能调用 Child 对象中不存在的方法了 Child::macro('show', new Father); // 输出:Father (new Child)->show();
Method
public static function mixin($mixin) { // 通过反射获取该对象中所有公开和受保护的方法 $methods = (new ReflectionClass($mixin))->getMethods( ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED ); foreach ($methods as $method) { // 设置方法可访问,因为受保护的不能在外部调用 $method->setAccessible(true); // 调用 macro 方法批量创建宏指令 static::macro($method->name, $method->invoke($mixin)); } } // 实际使用 class Father { public function say() { return function () { echo 'say'; }; } public function show() { return function () { echo 'show'; }; } protected function eat() { return function () { echo 'eat'; }; } } class Child { use \Illuminate\Support\Traits\Macroable; } // 批量绑定宏指令 Child::mixin(new Father); $child = new Child; // 输出:say $child->say(); // 输出:show $child->show(); // 输出:eat $child->eat();
上記のコード
mixinクラスメソッドをマクロクラスにバインドできます。メソッドはクロージャの型を返す必要があることに注意してください。
メソッド
public static function hasMacro($name) { return isset(static::$macros[$name]); }
と Macroable::__callStatic
method
<pre class="brush:php;toolbar:false">public function __call($method, $parameters)
{
// 如果不存在这个宏指令,直接抛出异常
if (! static::hasMacro($method)) {
throw new BadMethodCallException("Method {$method} does not exist.");
}
// 得到存储的宏指令
$macro = static::$macros[$method];
// 闭包做一点点特殊的处理
if ($macro instanceof Closure) {
return call_user_func_array($macro->bindTo($this, static::class), $parameters);
}
// 不是闭包,比如对象的时候,直接通过这种方法运行,但是要确保对象有`__invoke`方法
return call_user_func_array($macro, $parameters);
}
class Child
{
use \Illuminate\Support\Traits\Macroable;
protected $name = 'father';
}
// 闭包的特殊处理,需要做的就是绑定 $this, 如
Child::macro('show', function () {
echo $this->name;
});
// 输出:father
(new Child)->show();</pre>
について話しましょう。 上記の操作では、マクロをバインドするときに、クロージャ内の
を通じて Child## を呼び出すことができます。 # 属性は、
__call メソッドで
Closure::bindTo メソッドを使用するためです。
公式 Web サイトでは、
Closure::bindTo
Laravel のクラスにマクロを追加する
たとえば、Illuminate\Filesystem\Filesystem::class
、このクラスにメソッドを追加したいのですが、内部のコードには触れません。 マクロ命令を
# 1. 次に、新しく追加したメソッドをテストするためのテスト ルートを追加します。
Laravel の Eloquent ORM の分析
Laravel の基本的な移行の分析#
以上がLaravelでマクロ可能なマクロを使用する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。