当前位置: 首页 > news >正文

揭秘laravel-blade-javascript责任链模式:6个Transformer协作转换任意值到JavaScript

揭秘laravel-blade-javascript责任链模式:6个Transformer协作转换任意值到JavaScript

【免费下载链接】laravel-blade-javascriptA Blade directive to export variables to JavaScript项目地址: https://gitcode.com/gh_mirrors/la/laravel-blade-javascript

laravel-blade-javascript是一个 Laravel 扩展包,它提供了一个@javascriptBlade 指令,让你可以把 PHP 变量一键导出到 JavaScript中:在模板里写一行@javascript('key', 'value'),页面渲染后浏览器里就能直接用key这个变量。

那么问题来了:PHP 里什么都有——字符串、布尔、数组、对象、null……它是怎么把"任意值"安全地变成合法的 JavaScript 的?答案就是本项目源码中隐藏的责任链模式(Chain of Responsibility)🎯

先看效果:一个指令打通 PHP 与 JavaScript

安装只需一条命令:

composer require spatie/laravel-blade-javascript

在 Blade 模板中使用:

@javascript('key', 'value')

页面最终输出:

<script>window['key'] = 'value';</script>

如果不想污染全局,还可以在配置文件 config/blade-javascript.php 里设置namespace,把变量收进独立命名空间,避免命名冲突。

责任链模式是什么?为什么这里需要它

想象一支流水线:一个值进入后,依次询问每个转换器——"你能处理它吗?"谁能处理,谁来接手,其他人继续待命。这就是责任链模式:

  • 每个节点只负责一种职责(单一职责,代码短小好测试)
  • 新增类型只需加一个节点,不用改老代码(开闭原则)
  • 拒绝处理时自动"传递"给下一个,链路末段统一兜底报错

laravel-blade-javascript 正是这样实现的。所有转换器都实现同一个接口,定义在 src/Transformers/Transformer.php:

interface Transformer { public function canTransform($value): bool; // 我能处理吗? public function transform($value); // 那就交给我 }

两个方法、一种契约,六个实现。

Renderer:责任链的"总调度"

整条链的发起者是 src/Renderer.php。它在构造函数里注册了 6 个转换器,按固定顺序组成链条:

protected $transformers = [ ArrayTransformer::class, BooleanTransformer::class, NullTransformer::class, NumericTransformer::class, ObjectTransformer::class, StringTransformer::class, ];

真正的"传递"发生在getTransformer()方法中——逐个询问,命中即返回:

public function getTransformer($value): Transformer { foreach ($this->getAllTransformers() as $transformer) { if ($transformer->canTransform($value)) { return $transformer; } } throw Untransformable::noTransformerFound($value); }

一句话概括:先问遍所有人,没人能处理就抛Untransformable异常,错误信息直接告诉你是哪个值没被转换,排查体验极佳。

6个Transformer逐一揭秘:各自认领什么任务?

1️⃣ ArrayTransformer —— 数组与集合的"翻译官"

位于 src/Transformers/ArrayTransformer.php,用is_array()认领所有数组,直接json_encode()变成 JSON 对象。这是 PHP 数组与 JS 对象之间最自然的桥梁。

2️⃣ BooleanTransformer —— 布尔值的类型对齐器

位于 src/Transformers/BooleanTransformer.php。PHP 的true/false恰好和 JavaScript 同名,所以转换几乎"零成本",保证前端拿到的是布尔类型而不是字符串"1"

3️⃣ NullTransformer —— 空值的兜底者

位于 src/Transformers/NullTransformer.php。PHP 的null对应 JS 的null,短小精悍但必不可少——否则一个 null 值就可能整条链跑空。

4️⃣ NumericTransformer —— 数字的直通车

位于 src/Transformers/NumericTransformer.php,同时认领intfloat。它做的几乎是"原样放行",因为数字在两种语言里的字面量写法一致,是整条链里最轻松的节点。

5️⃣ ObjectTransformer —— 对象的多策略专家

位于 src/Transformers/ObjectTransformer.php,是链中最"有想法"的一位,按优先级尝试三种策略:

  1. 对象有toJson()方法?直接调用(兼容 Laravel Eloquent 模型)
  2. 对象实现了JsonSerializable或是StdClass?交给json_encode()
  3. __toString()方法?退化成字符串处理

三条路都走不通,才会抛出Untransformable异常。

6️⃣ StringTransformer —— 字符串的"安全卫士"

位于 src/Transformers/StringTransformer.php。它不只是加引号,内部还有一套转义逻辑:对反斜杠、单引号、换行以及<>做替换——最后一步防止用户输入提前闭合 script 标签,规避 XSS 注入风险。这是整条链里安全含金量最高的节点。

协作全景图:一个值如何走完责任链

顺序Transformer认领条件转换结果示例
1ArrayTransformeris_array(){"id":1}
2BooleanTransformeris_bool()true/false
3NullTransformeris_null()null
4NumericTransformeris_int()is_float()42/3.14
5ObjectTransformeris_object()JSON 或转义字符串
6StringTransformeris_string()'hello'

@javascript('user', $user)为例,一次完整的调用流程:

  1. Renderer 接收参数normalizeArguments()把多种传参写法(键值对、数组、Collection)统一成key => value结构
  2. 逐个变量走链buildVariableInitialization()为每个值调用optimizeValueForJavaScript()
  3. 责任链选人getTransformer()按上表顺序询问 6 位 Transformer,命中者完成转换
  4. 拼装输出:所有window['key'] = 值;语句拼接到模板视图 src/Renderer.php 中渲染成<script>标签

如果 6 位都拒绝,异常定义在 src/Exceptions/Untransformable.php 中的Untransformable会被抛出,开发阶段立刻暴露问题,而不是让前端拿到一段坏代码。

想扩展?加一个节点就行

这正是责任链模式的红利:假设你想支持DateTime类型,只需新建一个类实现Transformer接口(canTransform判断instanceof DateTimetransform输出new Date('...')),再把它加进 Renderer 的$transformers数组——原有 6 个转换器一行都不用动。测试代码 tests/BladeTest.php 展示了如何断言转换结果,可作为扩展时的参考。

小结:小而美的设计教科书

laravel-blade-javascript 只有十几行核心代码,却把责任链模式用得恰到好处:

  • 单一职责:6 个 Transformer,一个文件一类值,各司其职
  • 统一契约canTransform+transform两方法接口,扩展零门槛
  • 链路兜底Untransformable异常让"无法转换"变得可见、可排查
  • 安全内建:StringTransformer 的转义逻辑堵住 XSS 后路

如果你正在写自己的 Laravel 包,不妨看看 src/ 下的这份源码——它证明了:经典设计模式哪怕用在一个小工具里,也能让代码结构清晰得令人愉悦 ✨

【免费下载链接】laravel-blade-javascriptA Blade directive to export variables to JavaScript项目地址: https://gitcode.com/gh_mirrors/la/laravel-blade-javascript

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

http://www.cnnetsun.cn/news/4191900.html

相关文章:

  • 10分钟导入600+设备红外代码:Flipper Zero红外遥控完整实操
  • AI原生SDLC实战:基于Agent的智能软件交付循环构建指南
  • 动态多智能体路径规划与任务调度在机器人蜂窝仓储系统中的工程实践
  • YDF高级特征指南:时序、多维、预训练嵌入特征喂给决策树的简单方法
  • ComfyUI脸部修复实战:MiniMax H3与T8节点应用指南
  • C++可变参数模板:从语法到实战的范式革命
  • faiss_tips:如何把FAISS向量搜索搬上GPU,3行代码让检索速度起飞
  • 完整指南:KeqingNiuza 原神祈愿记录分析与五星保底预测的实战拆解
  • 一文读懂SimuPy核心数学:连续时间与离散时间动力系统建模解析
  • Reachy Mini开源桌面机器人:3D打印运动控制到自定义行为的完整路径
  • LLM全栈学习路线:从Transformer到RAG与Agent实战
  • NoSleep 防休眠工具:3 分钟装好,再不被半夜黑屏打断
  • 打造专属搜索引擎门户:yacy_webclient_bootstrap二次开发完整清单(页面/颜色/导航)
  • 第16章 集合框架:List 与 Set
  • react-gsap 与 react-transition-group 集成实战:列表增删动画的优雅实现
  • Hashnode Starter Kit的SEO利器:Sitemap、RSS与JSON-LD结构化数据全解析
  • 数学建模实战指南:从思想到方法,掌握问题求解的核心框架
  • 代码解释器安全基准CIBER:构建AI智能体的安全防线
  • C++函数模板:从类型安全到泛型编程的实战指南
  • 数学建模竞赛论文写作指南:从结构解析到团队协作的实战技巧
  • C语言链表实现通讯录系统:数据结构与文件操作实战指南
  • 如何 3 条命令搞定网页文件下载:skills 自动浏览完整教程
  • Windows图标缓存损坏导致快捷方式图标变白的原理与修复方法
  • 为AI编码智能体引入证据条件化执行层,解决“过早承诺”难题
  • TGW 完整上手指南:从克隆到调参一次讲清
  • 如何手写一个高速日期解析器?LogViewer的FastDateTimeParser源码全解
  • 多智能体强化学习中的Sim-to-Real迁移:IDEA方法如何通过效果对齐解决动力学失配
  • 微信聊天记录导出完整教程:用 EchoTrace 一键配置、快速导出与排错
  • 3 步跑通 mmsegmentation 语义分割可视化:把训练状态看得一清二楚
  • 【前端知识点总结】Nginx 指南:从开发到生产的完美衔接