注:以下内容基于php 8.1,laravel 10, dcat admin 2
需求是这样的,需要在后台添加一个给用户手动充值的功能,我不想为了这么一个小功能单独开一个控制器,就直接在用户的UserController新增加了一个方法 recharge。
内容就是数据表单 form 相关的代码,再配上路由,就可以访问了。
1class UserController extends AdminController{2 // ...3 function recharge($id)4 {5 $model = Administrator::with(['roles']);6
7 return Form::make($model, function (Form $form) use ($id) {8
9 $form->title('充值');10
11 $form->text('money', '充值金额')12 ->required()13 ->rules(['numeric', 'min:0']);14 // ...2 collapsed lines
15 }16}发现问题
一切看上去都还正常,直到我在recharge页面点击了刷新,发现了问题,页面的样式全没了,只有光秃秃的html效果。
查了很多资料,总是不对症,<Dcat Admin中新建页面,第一次点击菜单,显示页面正常,浏览器刷新当前页会导致css,js等样式内容丢失,请问如何解决> 从这个文章下面的评论看,也说是需要使用$router->resource(...)来加载资源路由,而不能自定义。但是这样加载资源路由的话,就只能完全按独立控制器的方式来实现了,后续如果有类似的小功能,都是需要挨个创建独立的控制器,也太傻了。
定位问题
查了其他资料也无果,最后去看了下继承的类AdminController 源码,看看是怎么实现的默认表单页面form。
看到AdminController的源码,就感觉熟悉多了,什么index, show, edit之类,都在这里了,这里着重看了下edit方法:
1 public function edit($id, Content $content)2 {3 return $content4 ->translation($this->translation())5 ->title($this->title())6 ->description($this->description()['edit'] ?? trans('admin.edit'))7 ->body($this->form()->edit($id));8 }很清晰了,重点在最后一句,body中,需要包装一下recharge返回的form实例。
依葫芦画瓢,自己实现一个就好。
解决问题
为了图省事,直接把UserController中原来的recharge改名为_recharge,新建一个recharge来放上面的代码
1 // ...2 public function recharge($id, Content $content)3 {4 return $content5 ->title($this->title())6 ->description($this->description['edit'] ?? trans('admin.edit'))7 ->body($this->_recharge()->edit($id));8 }9 private function _recharge()10 {11 $model = Administrator::with(['roles']);12
13 return Form::make($model, function (Form $form) {14 $id = $form->getKey();9 collapsed lines
15
16 $form->title('充值');17
18 $form->text('money', '充值金额')19 ->required()20 ->rules(['numeric', 'min:0']);21 // ...22 }23 // ...注意 _recharge中,有些许改动。
这样,不论页面怎么刷新,都不会丢失样式css、js等了。
提交保存数据
后续发现这个recharge的数据表单,还是会往默认的form方法里提交保存数据,导致没有按照_recharge内的保存逻辑去存储数据。
解决思路同上,看AdminController的代码。
1 public function update($id)2 {3 return $this->form()->update($id);4 }对应着在UserController里创建
1 function recharge_update($id)2 {3 return $this->_recharge()->update($id);4 }同时,也配置一个put路由,到这个recharge_update方法上。
这里把这2个路由的代码都给出来吧,之前查资料看别人的文章发一半留一般的就很不爽,我在不扩大篇幅的情况下尽量写全一些
1 // ...2 $router->get('users/{id}/recharge', 'UserController@recharge')->name('users.recharge');3 $router->put('users/{id}/recharge', 'UserController@recharge_update')->name('users.recharge_update');4 // ..._recharge方法内需要改一下
1 // ...2 $form = Form::make($model, function (Form $form){3 $id = $form->getKey();4 $form->action(route('dcat.admin.users.recharge_update', $id));5 // ...这里主要是$form->action这句,指定了表单提交的页面。
提交后如何自定义保存逻辑,就写在_recharge中的saving里好了,如果不会,这个直接查文档就好。事件及表单响应 - saving
更好的实现方式
上述独立的用户充值表单页面做好之后,我发现了一种更好的实现方式,使用工具表单,弹出模态框(modal)进行操作,连路由都不需要定义。
这个后面单开一篇讲吧。