Cet article présente principalement l'utilisation des macros Macroable dans Laravel. Il a une certaine valeur de référence. Maintenant, je le partage avec vous. Les amis dans le besoin peuvent s'y référer
Définition de l'Encyclopédie Baidu :
Macro dans. l'informatique est un terme désignant le traitement par lots. De manière générale, une macro est une règle ou un modèle, ou une substitution de syntaxe, utilisée pour expliquer comment une entrée spécifique (généralement une chaîne) est convertie en une sortie correspondante (généralement une chaîne) selon des règles prédéfinies. Ce remplacement se produit au moment de la précompilation et est appelé extension de macro.
Je suis entré en contact pour la première fois avec les macros alors que je suivais un cours d'informatique de base à l'université et le professeur m'a parlé du bureau. A cette époque, l'enseignant n'y prêtait pas beaucoup d'attention lorsqu'il introduisait l'opération macro. Il se souvenait seulement que cette opération était très puissante et qu'elle pouvait faciliter le travail quotidien.
Aujourd'hui, nous allons parler des opérations de macro dans 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
Méthode
public static function macro($name, $macro) { static::$macros[$name] = $macro; }
Code très simple, d'après le commentaire du paramètre, $macro
peut passer une fermeture ou un objet, la raison pour laquelle les objets peuvent être passés est grâce à la méthode magique
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();
Macroable::mixin
>Cette méthode consiste à injecter le résultat de retour de la méthode d'un objet dans l'objet d'origine
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();
Comme vous pouvez le voir dans le code ci-dessus, mixin
peut lier une classe méthode à une classe de macro. Il convient de noter que la méthode doit renvoyer un type de fermeture.
Macroable::hasMacro
Méthode
public static function hasMacro($name) { return isset(static::$macros[$name]); }
Cette méthode est relativement simple et pas compliquée du tout. Elle détermine simplement s'il existe une macro. instruction. C'est généralement une bonne idée de vérifier avant d'utiliser des macros. Méthodes
Macroable::__call
et Macroable::__callStatic
C'est grâce à ces deux méthodes que nous pouvons effectuer des opérations de macro en plus de The. les méthodes d'exécution sont différentes, mais les codes sont pour la plupart les mêmes. Parlons de __call
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();
dans l'opération ci-dessus Lorsque nous lions la macro, les propriétés de $this
peuvent être appelées via Child
dans la fermeture car dans la méthode __call
Ici. nous utilisons la méthode Closure::bindTo
.
Explication du site officiel de Closure::bindTo
: copiez l'objet de fermeture actuel et liez l'objet $this spécifié et la portée de la classe.
De nombreuses classes dans Laravel utilisent des macros trait
Par exemple, IlluminateFilesystemFilesystem::class
, nous voulons ajouter une méthode à cette classe, mais nous ne toucherons pas au code qu'elle contient.
Il suffit d'ajouter des macros à la méthode AppProvidersAppServiceProvider::register
(vous pouvez également créer un nouveau fournisseur de services pour le gérer spécifiquement)
1. Ajoutez ensuite un itinéraire test pour tester notre méthode nouvellement ajoutée
2. Ensuite, ouvrez le navigateur et exécutez-le, vous constaterez que notre code peut s'exécuter normalement et afficher les résultats
Ce qui précède est l'intégralité du contenu de cet article, J'espère que cela sera utile. L'apprentissage de tout le monde est utile. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois !
Recommandations associées :
Analyse de l'ORM éloquent de Laravel
Analyse des migrations de base de Laravel
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!