owl-admin: 利用 Pipeline 实现任意组件可全局重写

写在前面

本文只是借用 owl-admin 中组件封装的例子, 给大家分享一种 Pipeline 的使用场景
欢迎大家探讨 Pipeline 的其他使用场景

至于 owl-admin , 只是一个基于 laravelamis 开发的又快又灵活的框架, 大家不必过多关心, 当然, 如果有想了解的也可以 点击这里 了解更多内容 🤣

什么是管道

使用 Pipeline 你可以将一个实例对象(object)在多个类之间传递,就像流水顺着管道依次流淌一般,层层传递,你就得到了从头至尾一系列执行操作的 “最终” 结果。

laravel 中许多地方都用了 Pipeline, 最典型的便是: Middleware

用一段简单的代码演示一下:

$pipeline = new \Illuminate\Pipeline\Pipeline(); // 原始传入数据 $user = [ 'name' => '张三', 'age' => 18, 'gender' => '男', ]; $result = $pipeline ->send($user) // ->via('run') // 你可以通过调用 via 方法指定一个方法名,Pipeline 会调用该方法, 替代默认的 handle 方法 ->through([ // 这里如果传入的是一个类名, Pipeline 会默认调用该类中的 handle 方法 GenderTransition::class, // handle 方法的参数是 $user (原始数据) 和 $next function ($user, $next){ // 这里也可以直接传入 闭包 // 这里的 $user 是上一个类传递过来的数据 // 假设: GenderTransition 类中, 将 gender 设置为了 女 // 那么, 这个方法中 $user['gender'] = '女' // 再次给 $user 添加属性 $user['address'] = 'M78 星云'; // 执行下一个类, 传递 $user return $next($user); }, // ... ]) ->then(function ($user) { // 最后一个类执行完后, 会执行 then 方法 // 你可以做你想做的事, 比如: $user['address'] .= ' 123456'; // 最后返回 $user return $user; }); var_dump($result); /* array(4) { ["name"]=> string(6) "张三" ["age"]=> int(18) ["sex"]=> string(1) "女" ["address"]=> string(15) "M78 星云 123456" } */


将管道应用到 owl-admin 的组件中

首先, 对 Pipeline 稍作封装

<?php namespace Slowlyo\OwlAdmin\Support\Cores; use Slowlyo\OwlAdmin\Admin; class AdminPipeline { /** * @param $key * @param $passable * @param callable|null $callback * * @return mixed */ public static function handle($key, $passable, callable $callback = null) { $do = fn($i) => $callback ? $callback($i) : $i; // 如果传入了回调函数, 则执行回调函数, 否则直接返回 $passable $pipes = Admin::context()->get($key, []); // 从框架上下文中获取管道内容 // 管道为空, 则直接返回原始数据, 稍微提升些许性能 if (blank($pipes)) { return $do($passable); } // 执行管道 return admin_pipeline($passable)->through($pipes)->then(fn($i) => $do($i)); } /** * 该方法用于设置管道, 它们通过 $key 来对应 * * @param array|mixed $pipes * * @return void */ public static function through($key, $pipes) { Admin::context()->set($key, $pipes); } }

这样, 我们只需要在调用到 handle 方法之前, 给框架的上下文中写入对应的管道内容, 就实现了逻辑的注入

结合 owl-admin 的组件特性

基于 amis 通过后端返回组件的 json 结构, 由前端渲染对应的组件

就可以实现以下逻辑:

// 所有组件在返回给前端之前, 都会执行这么一段代码 AdminPipeline::handle(static::class, $this->amisSchema); // - 由于要给所有的组件都加上这行代码, 不可能重复写 100 多遍吧 // - 所以这里把逻辑写在了所有组件的基类中 // - 通过 static::class 来获取当前使用的组件的类名 // 那么, 我们只需要在返回之前, 给框架上下文中添加管道内容即可 AdminPipeline::through( Button::class, // 这里对应到上面的 static::class [ // something... ] );

将逻辑完整的提取出来, 流程如下:

// 原本的结构 $schema = [ 'type' => 'button', 'label' => '按钮', 'level' => 'primary' ]; // 通过 Pipeline 处理, 得到的新的结构 $lastSchema = app(Pipeline::class) ->send($schema) ->through([ function ($schema, $next){ $schema['level'] = 'success'; // 修改按钮颜色 $schema['label'] = '我是个按钮'; // 替换按钮文字 $schema['icon'] = 'fa fa-add'; // 添加按钮图标 // 甚至可以返回个新的结构 //$schema = []; return $next($schema); } ]) ->then(fn($schema)=>$schema);

这么一来, 所有的基础组件就都支持了使用 Pipeline 来扩展, 或者是加一些基础属性

结合这个思路, 只需要给框架中做过一层封装的组件分别定义一些 key, 用于在上下文中设置管道内容, 那么页面内容基本上就都可以自定义了 👏

// 基础页面 const PIPE_BASE_PAGE = 'pipe_schema_base_page'; // 返回按钮 const PIPE_BACK_ACTION = 'pipe_schema_back_action'; // 批量删除按钮 const PIPE_BULK_DELETE_ACTION = 'pipe_schema_bulk_delete_action'; // 添加按钮 const PIPE_CREATE_ACTION = 'pipe_schema_create_action'; // 编辑按钮 const PIPE_EDIT_ACTION = 'pipe_schema_edit_action'; // 查看按钮 const PIPE_SHOW_ACTION = 'pipe_schema_show_action'; // 删除按钮 const PIPE_DELETE_ACTION = 'pipe_schema_delete_action'; // 行操作按钮 const PIPE_ROW_ACTIONS = 'pipe_schema_row_actions'; // 基础筛选 const PIPE_BASE_FILTER = 'pipe_schema_base_filter'; // 基础CRUD const PIPE_BASE_CRUD = 'pipe_schema_base_crud'; // 基础头部工具栏 const PIPE_BASE_HEADER_TOOLBAR = 'pipe_schema_base_header_toolbar'; // 基础表单 const PIPE_BASE_FORM = 'pipe_schema_base_form'; // 基础详情 const PIPE_BASE_DETAIL = 'pipe_schema_base_detail'; // 基础列表 const PIPE_BASE_LIST = 'pipe_schema_base_list'; // 导出按钮 const PIPE_EXPORT_ACTION = 'pipe_schema_export_action';
本作品采用《CC 协议》,转载必须注明作者和本文链接
啪嗒啪嗒啪嗒 (`・ω・´)つ_▃ <?php echo "PHP is the best language in the world!"; ?>
slowlyo
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 2

看起来好复杂

1年前 评论
iwzh 1年前