Laravel-admin 重写源码 自定义排序回调

简介: 有几个业务相关的配置信息需要管理后台灵活配置,且返回的数据要进行排序为了保证业务接口的请求速度,我们把这些配置信息接口做了缓存在管理后台进行form表单提交的时候清空缓存,保证数据及时更新(比如删除、修改之后要刷新缓存)测试阶段发现一个问题,laravel-admin 的 sortable 扩展和框架本身的form表单提交没有关系,执行排序的时候没有回调函数,导致排序操作后无法主动清除缓存。

背景


有几个业务相关的配置信息需要管理后台灵活配置,且返回的数据要进行排序

为了保证业务接口的请求速度,我们把这些配置信息接口做了缓存

在管理后台进行form表单提交的时候清空缓存,保证数据及时更新(比如删除、修改之后要刷新缓存)

测试阶段发现一个问题,laravel-adminsortable 扩展和框架本身的form表单提交没有关系,执行排序的时候没有回调函数,导致排序操作后无法主动清除缓存。


实现原理分析


我们可以在 form() 函数中 调用 $form->saved(function () {             HobbyInfo::flushCache();         }); 进行相关操作


但是拖拽排序保存是不会触发这个函数的。


<?php
namespace App\Admin\Controllers;
.
.
.
class HobbyInfoController extends AdminController
{
    /**
     * Title for current resource.
     *
     * @var string
     */
    protected $title = '用户爱好-一级分类';
    /**
     * Make a grid builder.
     *
     * @return Grid
     */
    protected function grid()
    {
        $grid = new Grid(new HobbyInfo());
        $grid->sortable();
        .
        .
        .
        return $grid;
    }
    /**
     * Make a show builder.
     *
     * @param mixed $id
     * @return Show
     */
    protected function detail($id)
    {
        $show = new Show(HobbyInfo::findOrFail($id));
        return $show;
    }
    /**
     * Make a form builder.
     *
     * @return Form
     */
    protected function form()
    {
        $form = new Form(new HobbyInfo());
        .
        .
        .
        //清空缓存
        $form->saved(function () {
            HobbyInfo::flushCache();
        });
        return $form;
    }
}


定位问题


  1. 点击【保存排序】按钮时查看网络请求,发现了一个不是我定义的路由 _grid-sortable_

微信图片_20221111230643.jpg


  1. 在项目中搜索这个路由,发现是扩展中的一个路由


微信图片_20221111230652.jpg


  1. 查看这个扩展相关的源码,发现拖拽排序是不会执行我们写的 form 表单提交相关方法的,源码内容如下:


<?php
namespace Encore\Admin\GridSortable\Controllers;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class GridSortableController extends Controller
{
    public function sort(Request $request)
    {
        $sorts = $request->get('_sort');
        $sorts = collect($sorts)
            ->pluck('key')
            ->combine(
                collect($sorts)->pluck('sort')->sort()
            );
        $status = true;
        $message = trans('admin.save_succeeded');
        $modelClass = $request->get('_model');
        try {
            /** @var \Illuminate\Database\Eloquent\Collection $models */
            $models = $modelClass::find($sorts->keys());
            foreach ($models as $model) {
                $column = data_get($model->sortable, 'order_column_name', 'order_column');
                $model->{$column} = $sorts->get($model->getKey());
                $model->save();
            }
        } catch (Exception $exception) {
            $status = false;
            $message = $exception->getMessage();
        }
        return response()->json(compact('status', 'message'));
    }
}


解决问题


  1. 因为我们有好几个配置模块,需要找到一种通用的配置方式,经过再三考虑,决定修改扩展的源码


  • 自定义回调函数 afterSort ,意为在排序之后执行
  • 通过阅读源码我们不难发现,我们是能够获得model对象的
  • 我们做下兼容判断,如果model中有 afterSort 的话,我们就执行
  • 这样,我们就可以在需要执行排序的model中,自定义afterSort方法,执行我们的操作,比如刷新缓存。


<?php
namespace Encore\Admin\GridSortable\Controllers;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class GridSortableController extends Controller
{
    public function sort(Request $request)
    {
        $sorts = $request->get('_sort');
        $sorts = collect($sorts)
            ->pluck('key')
            ->combine(
                collect($sorts)->pluck('sort')->sort()
            );
        $status = true;
        $message = trans('admin.save_succeeded');
        $modelClass = $request->get('_model');
        try {
            /** @var \Illuminate\Database\Eloquent\Collection $models */
            $models = $modelClass::find($sorts->keys());
            foreach ($models as $model) {
                $column = data_get($model->sortable, 'order_column_name', 'order_column');
                $model->{$column} = $sorts->get($model->getKey());
                $model->save();
            }
            //自定义回调
            if (method_exists($model, 'afterSort')) {
                $model->afterSort();
            }
        } catch (Exception $exception) {
            $status = false;
            $message = $exception->getMessage();
        }
        return response()->json(compact('status', 'message'));
    }
}


  1. 我们在自己的model中,比如我的兴趣爱好model,自定义 afterSort 函数就可以了


<?php
namespace App\Model;
use App\Model\Cache\CacheKey;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Spatie\EloquentSortable\Sortable;
use Spatie\EloquentSortable\SortableTrait;
class HobbyInfo extends CustomModel implements Sortable
{
    protected $table = 'tbl_hobby_info';
    protected $connection = 'footprint';
    protected $primaryKey = 'id';
    public $incrementing = true;
    use SortableTrait;
    public $sortable = [
        'order_column_name' => 'sort',
        'sort_when_creating' => true,
    ];
    //改了源码 添加了自定义回调
    public static function afterSort()
    {
        self::flushCache();
    }
    //清空缓存
    public static function flushCache()
    {
        $cacheKey = CacheKey::getCacheKey(CacheKey::TYPE_USER_SETTING_HOBBY_ALL);
        Cache::forget($cacheKey);
        Log::info('清空Hobby缓存');
    }
}


  1. 这样我们就通过修改源码,实现了自定义回调,在其他model中也可以通过这种方法触发排序后的操作。


微信图片_20221111230657.jpg


相关文章
|
6月前
|
数据安全/隐私保护
fastadmin中写接口是时Validate规则验证自定义如何用
fastadmin中写接口是时Validate规则验证自定义如何用
|
8月前
|
Python
|
负载均衡 前端开发 Java
Feign 踩坑指南 (接口返回泛型设置属性为null)
Feign 简介 Feign 的英文表意为“假装,伪装,变形”, 是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求,而不用像Java中通过封装HTTP请求报文的方式直接调用。Feign通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的请求,这种请求相对而言比较直观。
1218 0
Feign 踩坑指南 (接口返回泛型设置属性为null)
|
缓存 小程序 JavaScript
【微信小程序】缓存数据库操作类——prototype和ES6方法
将post数据在缓存数据库中的key,postList赋值给构造函数的this变量。这个postList必须和初始化数据库时设置的文章数据的key相同,否则无法读取数据。
88 0
|
开发者
Yii2.0的默认视图文件是什么?底层原理是什么?
Yii2.0的默认视图文件是什么?底层原理是什么?
|
JSON API PHP
【源码解读】TP框架参数注入,参数绑定
核心是:使用反射类,拿到需要执行的类、方法属性,然后分析传参的属性,在post、get、类属性等等参数中,按不同优先级搜寻符合注入条件的参数。 最终使用执行,并且提供组装正确的参数数组。 php的反射类,可以分析目标类的各种属性 方法列表、参数、私有共有属性、方法的类型等等 以下提供一个简单的列表
225 0
|
JavaScript 前端开发 搜索推荐
「后端小伙伴来学前端了」 Vue中 this.$set的用法 | 可用于修改对象中数组的某一个对象、 可用于更新数据到视图
「后端小伙伴来学前端了」 Vue中 this.$set的用法 | 可用于修改对象中数组的某一个对象、 可用于更新数据到视图
704 0
「后端小伙伴来学前端了」 Vue中 this.$set的用法 | 可用于修改对象中数组的某一个对象、 可用于更新数据到视图
|
测试技术
为什么Spartacus单元测试里对http返回的Observable对象调用subscribe时,会触发依赖注入的框架代码
为什么Spartacus单元测试里对http返回的Observable对象调用subscribe时,会触发依赖注入的框架代码
为什么Spartacus单元测试里对http返回的Observable对象调用subscribe时,会触发依赖注入的框架代码
|
JavaScript
JFinal 参数校验插件扩展,让后台参数校验像js一样方式好用
一、插件实现 插件的功能就是加载校验规则,实现代码如下 package com.nmtx.plugins.validation; import java.util.Properties; import com.

热门文章

最新文章