Laravel 底层 - 一些宏
你好 ?
您是否经常希望获得一个集合或字符串助手中不存在的方法?你开始链接方法,结果发现其中一个方法丢失了,结果却碰壁了。老实说,这是可以理解的;你知道,框架是一刀切的东西。我多次发现自己处于这种情况。每次,在深入研究如何扩展框架之前,我都会检查我想要扩展的内容是否可宏。但这意味着什么?这正是我们将要探索的!
WTF 是宏吗? ?
假设我们有这个 JWT:
$jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';
我们需要提取标题:
str($jwt) ->before('.') ->fromBase64() ->fromJson(); // does not exist ? // BadMethodCallException Method Illuminate\Support\Stringable::fromJson does not exist.
fromJson() 不存在?当然,人们可以简单地这样做:
json_decode(str($jwt)->before('.')->fromBase64());
但是这有什么乐趣呢?另外,这是我的文章?
所以,我们需要一种方法来扩展 Stringable 类。有几种方法可以做到这一点,但 Laravel 提前思考,它知道开发人员可能想要添加自定义方法,因此它使类可宏,或者像我喜欢的那样,可扩展。
如果您检查 IlluminateSupportStringable 类,您会看到它使用 Macroable 特征。
让我们继续扩展课程吧。在AppServiceProvider中,添加以下内容:
<?php namespace App\Providers; use Illuminate\Support\Stringable; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function boot(): void { Stringable::macro('fromJson', function (bool $associative = true) { return json_decode($this->value, $associative); }); } }
现在让我们重新运行代码:
str($jwt) ->before('.') ->fromBase64() ->fromJson(); // ["alg" => "HS256", "typ" => "JWT"]
效果完美吗?但现在,您可能想知道,这是如何运作的? $this->value 到底是什么?哈利波特里发生了什么?
揭开魔法的面纱?
我们知道Stringable类使用Macroable特征,它提供了macro()方法。让我们仔细看看它的作用:
// src/Illuminate/Macroable/Traits/Macroable.php /** * Register a custom macro. * * @param string $name * @param object|callable $macro * * @param-closure-this static $macro * * @return void */ public static function macro($name, $macro) { static::$macros[$name] = $macro; }
这非常简单,它只是将回调保存到静态宏数组中。现在,如果我们进一步检查该特征,我们会发现 __call 方法,每次调用不存在的方法时都会触发该方法。在我们的例子中,就是 fromJson()。让我们深入了解一下:
/** * 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(sprintf( 'Method %s::%s does not exist.', static::class, $method )); } $macro = static::$macros[$method]; if ($macro instanceof Closure) { $macro = $macro->bindTo($this, static::class); } return $macro(...$parameters); }
首先,它检查宏是否已注册,fromJson() 就是这种情况,然后从宏数组中获取回调(或对象)。现在我们来看看魔术,如果宏是一个闭包(如我们的例子),它会调用bindTo(),它本质上告诉闭包$this应该引用作为第一个参数传递的任何内容。在本例中,它是 Stringable 实例,它恰好具有 $value 属性。
// $this here is the stringable // $this inside the closure is now referencing the stringable class $macro->bindTo($this, static::class);
这就是为什么我们可以做 $this->value。
我们可以做得更好:Mixins?
我还想告诉你一件事!当我们多次扩展同一个类时,服务提供者可能很快就会变得混乱。我们可以将所有自定义宏提取到一个名为 Mixin 的类中。
让我们创建一个 StringableMixin:
$jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';
现在,在 AppServiceProvider 中,我们可以注册这个 mixin:
str($jwt) ->before('.') ->fromBase64() ->fromJson(); // does not exist ? // BadMethodCallException Method Illuminate\Support\Stringable::fromJson does not exist.
就是这样!现在我们可以做:
json_decode(str($jwt)->before('.')->fromBase64());
基本上是一样的,只是更干净一点。
如果您对它的工作原理感到好奇,Macroable 特征上的 mixin() 方法使用反射 API。它从 Mixin 类中检索所有公共方法,期望每个方法返回一个闭包,然后将闭包注册为宏,就像我们之前看到的那样。
糟糕的 IDE?
嗯,正如您所看到的,有很多神奇的事情发生,IDE 不知道定义的宏。如果您在团队中工作,其他开发人员也不会知道这些宏,这不好。幸运的是,有一些工具可以帮助您做到这一点。 Laravel IDE 帮助程序包是一个免费开源选项。
您可以安装该软件包并生成 _ide_helper.php 文件,然后就可以开始了。
就这样结束了..
我们的示例相当简单,但是您可以将宏推得更远,因为 Laravel 附带的大多数常见类都是可宏的。例如,您可以添加一个新的 apiResponse() 宏,或者您认为在应用程序逻辑中非常常见并且重复次数过多的任何内容。但不要做得太过分。宏增加了新的复杂性,在团队中工作时,它们可能会令人困惑。
Soo,每当您感觉应用程序缺少某些内容,但框架本身没有缺少某些内容时,请使用宏?
以上是Laravel 底层 - 一些宏的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

在PHP中,应使用password_hash和password_verify函数实现安全的密码哈希处理,不应使用MD5或SHA1。1)password_hash生成包含盐值的哈希,增强安全性。2)password_verify验证密码,通过比较哈希值确保安全。3)MD5和SHA1易受攻击且缺乏盐值,不适合现代密码安全。

PHP类型提示提升代码质量和可读性。1)标量类型提示:自PHP7.0起,允许在函数参数中指定基本数据类型,如int、float等。2)返回类型提示:确保函数返回值类型的一致性。3)联合类型提示:自PHP8.0起,允许在函数参数或返回值中指定多个类型。4)可空类型提示:允许包含null值,处理可能返回空值的函数。

PHP主要是过程式编程,但也支持面向对象编程(OOP);Python支持多种范式,包括OOP、函数式和过程式编程。PHP适合web开发,Python适用于多种应用,如数据分析和机器学习。

在PHP中使用预处理语句和PDO可以有效防范SQL注入攻击。1)使用PDO连接数据库并设置错误模式。2)通过prepare方法创建预处理语句,使用占位符和execute方法传递数据。3)处理查询结果并确保代码的安全性和性能。

PHP和Python各有优劣,选择取决于项目需求和个人偏好。1.PHP适合快速开发和维护大型Web应用。2.Python在数据科学和机器学习领域占据主导地位。

PHP在数据库操作和服务器端逻辑处理中使用MySQLi和PDO扩展进行数据库交互,并通过会话管理等功能处理服务器端逻辑。1)使用MySQLi或PDO连接数据库,执行SQL查询。2)通过会话管理等功能处理HTTP请求和用户状态。3)使用事务确保数据库操作的原子性。4)防止SQL注入,使用异常处理和关闭连接来调试。5)通过索引和缓存优化性能,编写可读性高的代码并进行错误处理。

PHP用于构建动态网站,其核心功能包括:1.生成动态内容,通过与数据库对接实时生成网页;2.处理用户交互和表单提交,验证输入并响应操作;3.管理会话和用户认证,提供个性化体验;4.优化性能和遵循最佳实践,提升网站效率和安全性。

PHP适合网页开发和快速原型开发,Python适用于数据科学和机器学习。1.PHP用于动态网页开发,语法简单,适合快速开发。2.Python语法简洁,适用于多领域,库生态系统强大。
