Voyager 的使用及二次开发
主要整理了我对 Laravel 的后台开源项目 Voyager 的一点经验。
一、简介
做一个 Web 系统,后台是必须的,后台大致可以分为两类:
后端导向
这里以 Laravel 为例,这类后台的特点是可以直接通过关联了数据表的 Model 来轻易的创建 CURD(增删改查),这样可以省去大量控制器 CURD 的代码。后端具有更强的主导性。
- Voyager : Blade + Laravel
- Laravel-Admin : Laravel
- Laravel Nova : Laravel 官方开发,但是付费
前端导向
这种前端具有更强的主导性。
- Vue-Element-Admin : Vue + Element
- iView-Admin : Vue + iView
本文重点
在此主要介绍的是 Voyager,如上所述,Voyager 可以轻易的根据 Model 自动创建 BREAD(即 CURD),这样你可以省去写控制器及方法的代码,并且 Voyager 支持二次开发,具有足够高的定制性。
至于 Voyager 的缺点,主要还是前端是用的 Blade 写的,虽然 Blade 是 Laravel 自带提供的前端模板引擎,但是对于飞速发展的前端框架来说,Vue 是个更好的解决方案。
本文主要是介绍我自己在使用 Voyager 中遇到的一些问题和解决方案,和一些二次开发时的经验。
二、安装
1. 下载包
先把包下载过来
composer require tcg/voyager
2. 设置语言环境
设置环境为中文
config\app.php
'locale' => 'zh_CN',
3. 执行安装
# 正常安装
php artisan voyager:install
# 假数据安装
php artisan voyager:install --with-dummy
# 把一个用户设置为可登陆的管理员
php artisan voyager:admin your@email.com
# 新建一个可登陆的管理员
php artisan voyager:admin your@email.com --create
假数据安装下的账号和密码:
email: admin@admin.com
password: password
三、二次开发
Voyager 的二次开发主要有三种形式:覆写视图,覆写路由,继承控制器。
1. 覆写视图
视图层的二次开发可以参照官方文档,大致思路就是在 resource 下建立一个和 vendor 中包目录下一样的目录结构,复制你想要重写的视图内容文件,然后以此为基础进行修改即可。
包目录下的
image-20180821165431966.png
自己的开发目录
image-20180821165537551.png
方式一:修改 blade
这一层只需要按照 blade 模板引擎的语法对文件进行修改即可。
同时如果有这样一个需求:对于所有 post,我只想让 post 的创建者看到,即每个管理员只能看到自己创建的 post。但是在 Voyager 默认创建好 BREAD 之后,Voyager 中的权限管理只能做到用户要么全看到,要么全看不到。
这个时候,就可以修改 blade,在其中加一个过滤操作即可解决问题。
但是值得注意的是:这样并不优雅,因为更好的逻辑应该是在查数据库时就只取所需的数据,而不是这样全取出来再过滤。但是这种方法比较简单,改动的代码量也小。所以见仁见智啦。
方式二:Vue 单文件组件
这种方式是通过 Vue 写单文件组件,然后直接像 HTML 标签一样插入 Blade 中,然后其中的内容就随便你 Vue 怎么写了。
/resources/assets/js/app.js
// 单文件组件
Vue.component('worlduc-video', require('./components/Index-Video.vue'));
/resources/views/video.blade.php
<div id="app" style="width:100%;height:100%;">
<worlduc-video></worlduc-video>
</div>
额外
-
若是想要添加子页面,并且是带那种左侧 admin 导航的子页,在新建的 blade 文件中添加如下即可:
@extends('voyager::master')
-
若是添加的子页面想要放在登陆保护后,则添加其路由至
admin.user
中间件后// 自定义的页要加到认证后的,就加到这个里面 Route::group(['middleware' => 'admin.user'], function () { // 课程信息页 Route::view('/admin/teams/member/{teamId}', 'addMember'); // 首页 Route::view('/', 'index'); });
-
若想要一个用户可以登录的 Voyager 并看到其中的内容,必须给予 admin 的 browse 权限,否则无法登陆成功。
2. 覆写路由
这也是官方文档中明确支持的一种方式,能够将本来 Voyager 定义的一些路由,比如登陆,用自己的控制器和对应方法去替代。
Route::get('/', function () {
return view('welcome');
});
Route::group(['prefix' => 'admin'], function () {
// Voyager 原本的路由
Voyager::routes();
// 覆盖了原先的登录,添加了自定义的本身认证
Route::post('login', 'LoginController@postLogin')->name('voyager.login');
// 覆盖原先的注销
Route::post('logout', 'LoginController@postLogout')->name('voyager.logout');
});
3. 覆写控制器
控制器的重写,官方文档也写的足够详细了,首先在 config/voyager.php
中如下定义:
'controllers' => [
'namespace' => 'App\\Http\\Controllers\\Voyager',
],
然后运行 php artisan voyager:controllers
,这样控制器就会被创建到你的控制器目录,而这些控制器是继承自包中原先的控制器,如果你不覆写,还是能正常工作,如果你想进行自己的控制,那么就可以直接重写对应的方法。
4. 自定义控制器
除了上面覆写控制器的方法,你还可以看到在创建 BREAD 时,可以直接选择控制器,而这个控制器完全可以由你自己写,但是我并没有实践,BREAD 对应的增删改查操作应该对应的是控制器什么方法名,有兴趣的同学可以去看一下源码。
四、其他
除了上面的二次开发外,还有其他一些使用的的经验和实践,整理如下:
1. 部分字段自定义 create
现在有一个需求,我需要在一个表中插入一条数据,这条数据由三个字段组成,分别为 A、B、C。其中 B、C 我让用户自己输入,但是 A 我想要系统读取用户的信息来自动填入(比如读取用户的 ID,用来标识这条数据的创建者)。想想该怎么做呢?
一般来说,我们可以先考虑一下数据存储过程中需要用到的两个东西:Controller 和 Model,其中 Model 可以试着一个 attributes 属性来设置字段的默认值,但是这个属性要求都为静态值,是无法使用变量的。Controller 的话可以重写 Controller,修该逻辑即可,但是重写 Controller 其实代码量还是比较大的。有没有更加简单的办法呢?当然是有的!
方法一
在 bread 中设置字段为 hidden 并在可选细项中设置一个默认值,然后在模型中配置一个修改器,设置成你想要的值即可。
image-20180822145611512.png
public function setCreaterIdAttribute($value)
{
$this->attributes['creater_id'] = Cookie::get('user_id');
}
为什么要配置这个默认值呢?因为模型中的修改器只有在这个字段被设置了值才能成功触发。
方法二
不在可选细项配置默认值,只添加修改器即可:
// 让你想要设置的值在其他修改器中顺便被添加即可
public function setTeamNameAttribute($value)
{
$this->attributes['team_name'] = $value;
$this->attributes['creater_id'] = Cookie::get('user_id');
}
方法三
配置一个关系,按照图中勾选即可(其实 creater_id 那只需勾选『添加』便可达到效果,其他不影响)
image-20181023151613114.png
public function setCreaterIdAttribute($value)
{
$this->attributes['creater_id'] = Cookie::get('id');
}
2. datetimepicker 无法显示的 bug
覆写 master.blade.php,添加如下:
<!-- datatimepicker -->
<link rel="stylesheet" href="/css/bootstrap-datetimepicker.min.css">
// 这个 css 添加到上方合适位置
// css 自行下载 https://github.com/Eonasdan/bootstrap-datetimepicker/releases
<script type="text/javascript" src="{{ voyager_asset('js/app.js') }}"></script>
// 这一行是本来有的
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.1/moment-with-locales.js"></script>
<script>
moment.locale("zh-cn");
</script>
// 上面是设置语言,不过语言设置为中文会格式化报错
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/js/bootstrap-datetimepicker.min.js"></script>
出现 bug 的原因是其引用的一个 js 插件有 bug,指定一个没有 bug 的版本即可。
3. 表单字段可为空如何控制
在进行新建或编辑时,你会发现有些字段是必填的,而有些字段是非必填,但是并没有看到有一个控制的选项。其实这个是根据数据表的字段是否可为 NULL
控制的。但其实这个设定存在不少 bug:
- 如果输入空白符,前端会认为你填写了数据而放行,但是后端会报错
- 对于下拉选择,如果你选择的是
None
,并提交而这个字段又设置未非空的话也会报错。
所以我建议还是覆写 edit-add
这个 blade,添加 js 进行控制。
4. Voyager 配置完毕后如何导出设置
Voyager 的后台一些设置是保存在数据库中的,建议使用 orangehill/iseed
这个插件来将数据库的数据转换为 seeder,然后添加 Git 进行管理即可。
五、总结
Voyager 是一个非常不错的后台模板,功能齐全,颜值高,能够快速的搭建一个好用的后台,但是其中存在的小 bug 还是比较多,如果是作为开发者内部团队简单使用远远足够,但是若作为一个开放给外部用户使用,还需针对各个小 bug 进行修复,因为只有针对角色的权限分配,不能根据资源的创建者分配更细的权限,所以还需额外部署对应的逻辑。
本作品采用《CC 协议》,转载必须注明作者和本文链接
非常不错。之前找后台的时候也找到了这个,苦于对于laravel的研究不深。怕出问题没有及时的解决方案,所以使用了laravel-admin。毕竟国人开发,反馈问题可以得到快速回复。
不过内心还是想使用下voyager的。 先收藏下
快速后台用的最顺手的还是 laravel-admin,本地化后各种改功能很顺手,Nova 使用后还是很不习惯。。。。可能是深度不够。哈哈。。。
你还是会使用laravel-admin的 因为 太慢了 一个页面几百个查询
voyager 默认使用的是users表, 怎么修改为admins表? :cry:
对于Voyager的文档,本人进行了翻译,查看Voyager中文文档,希望对大家有所帮助
请教下,voyager后台利用file上传的视频文件怎么在前台展示呀? 数据库获取到存储视频的字段内容为:[{"download_link":"blogs\November2022\GlZU26tKxdxZjB7p2uv9.mp4","original_name":"002 \u6536\u8d27 \u8f6c\u5165\u786e\u8ba4 \u8de8\u533a\u8f6c\u5165\u786e\u8ba4.mp4"}]
## 前台视图如何展示视频呀,后台能看到,也能获取到真实地址。