dcat-admin
1. ScaffoldController.php
2. scaffold.blade.php
3. ModelCreator.php
4. ControllerCreator.php
5. FormCreator.php
6. GridCreator.php
修改列表页数据库字段翻译
第一种:
protected function grid()
{
$model = JhTypeModel::where('click','>',0);
return Grid::make($model, function (Grid $grid) {
$grid->id->sortable();
$grid->column('title','标题');
$grid->column('click','点击数');
$grid->quickSearch('id','title');
$grid->filter(function (Grid\Filter $filter) {
$filter->equal('id');
$filter->equal('title');
});
});
}
第二种:
传入关联模型
protected function grid()
{
//关联模型
$model = Model::with('...')->where(...);
return Grid::make($model, function (Grid $grid) {
...
});
}
protected function detail($id)
{
//关联模型
$model = HomestayModel::with(['chengshi','zousheng','guojium']);
return Show::make($id, $model, function (Show $show) {
$show->width(6)->field("guojium.name",'国家');
$show->width(6)->field('zousheng.ywmc', '州省');
$show->width(6)->field('chengshi.name', '城市');
});
}
通过display($callback)方法来格式化显示输出
$grid->column('text')->display(function($text) {
return str_limit($text, 30, '...');
});
// 添加不存在的字段
$grid->column('full_name')->display(function () {
return $this->first_name.' '.$this->last_name;
});
$form->image('jsjt_xsws')->uniqueName()->maxSize(40960);
弹出模态框 (modal)
modal
方法可以把内容隐藏,点击按钮的时候显示在表格下一行
$grid->column('content')
->display('查看') // 设置按钮名称
->modal(function ($modal) {
// 设置弹窗标题
$modal->title('标题 '.$this->username);
$card = new Card(null, $this->content);
return "<div style='padding:10px 10px 0'>$card</div>";
});
// 也可以通过这种方式设置弹窗标题
$grid->column('content')
->display('查看') // 设置按钮名称
->modal('弹窗标题', ...);
模态框异步加载 显示
$grid->post->display('家庭成员')->modal('JsFamily', JsFamily::make(['jtcy' => $grid->id]));
<?php
namespace App\Admin\Renderable;
class JsFamily extends LazyRenderable
{
public function render()
{
// 获取ID
$jtcy = $this->jtcy;
// 获取其他自定义参数
// $type = $this->post_type;
$data = JsFamilyModel::where('jtcy', $jtcy)
// ->where('type', $type)
// ->get(['id', 'name','js_applicant'])
->get(['name','js_surname2','js_applicant','js_cy_sex','id'])
->toArray();
$newData = [];
foreach ($data as $key => &$value) {
$tt = [];
$tt['name'] = $value['name'];
$tt['js_surname2'] = $value['js_surname2'];
$tt['js_applicant'] = $value['js_applicant'];
$tt['js_cy_sex'] = $value['js_cy_sex'];
$tt['link'] = "<a href='".admin_url('/jsfamily/'.$value['id'].'/edit'."' target='_blank'>查看详情</a>");
$newData[] = $tt;
}
$titles = [
// 'User ID',
'姓名',
'姓',
'关系',
'性别',
''
];
return Table::make($titles, $newData);
}
}
多选
下拉选框单选 (select)
$form->select($column[, $label])->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name']);
或者从 api 中获取选项列表:
$form->select($column[, $label])->options('/api/users');
其中 api 接口的格式必须为下面格式:
[
{
"id": 9,
"text": "xxx"
},
{
"id": 21,
"text": "xxx"
},
...
]
控制器 action 的代码示例如下:
public function city(Request $request)
{
$provinceId = $request->get('q');
return ChinaArea::city()->where('parent_id', $provinceId)->get(['id', DB::raw('name as text')]);
}
下拉选框联动 (load)
select 组件支持父子关系的单向联动:
$form->select('province')->options(...)->load('city', '/api/city');
$form->select('city');
其中 load('city', '/api/city'); 的意思是,在当前 select 的选项切换之后,会把当前选项的值通过参数 q, 调用接口 /api/city,并把 api 返回的数据填充为 city 选择框的选项,其中 api/api/city 返回的数据格式必须符合:
[
{
"id": 9,
"text": "xxx"
},
{
"id": 21,
"text": "xxx"
},
...
]
下拉选框多选 (multipleSelect)
注入这个字段的数据(从数据库查出来的)可以是一个以
,
隔开的字符串,也可以是json
字符串或array
数组。
$form->multipleSelect($column[, $label])
->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name'])
->saving(function ($value) {
// 转化成json字符串保存到数据库
return json_encode($value);
});
多选框可以处理两种情况,第一种是 ManyToMany
的关系。
class Post extends Models
{
public function tags()
{
return $this->belongsToMany(Tag::class);
}
}
return Form::make(Post::with('tags'), function (Form $form) {
...
$form->multipleSelect('tags')
->options(Tag::all()->pluck('name', 'id'))
->customFormat(function ($v) {
if (! $v) {
return [];
}
// 从数据库中查出的二维数组中转化成ID
return array_column($v, 'id');
});
});
下拉选框多选 (multipleSelect)
$form->multipleSelect('tag')->options('api/housetag')->saving(function ($value) {
return implode(';', $value);
});;
表格选择器 (selectTable) 多选
use App\Admin\Renderable\UserTable;
use Dcat\Admin\Models\Administrator;
$form->selectTable($field)
->title('弹窗标题')
->dialogWidth('50%') // 弹窗宽度,默认 800px
->from(UserTable::make(['id' => $form->getKey()])) // 设置渲染类实例,并传递自定义参数
->model(Administrator::class, 'id', 'name'); // 设置编辑数据显示
// 上面的代码等同于
$form->selectTable($field)
->from(UserTable::make(['id' => $form->getKey()])) // 设置渲染类实例,并传递自定义参数
->options(function ($v) { // 设置编辑数据显示
if (! $v) {
return [];
}
return Administrator::find($v)->pluck('name', 'id');
});
定义渲染类如下,需要继承 Dcat\Admin\Grid\LazyRenderable
<?php
namespace App\Admin\Renderable;
use Dcat\Admin\Grid;
use Dcat\Admin\Grid\LazyRenderable;
use Dcat\Admin\Models\Administrator;
class UserTable extends LazyRenderable
{
public function grid(): Grid
{
// 获取外部传递的参数
$id = $this->id;
return Grid::make(new Administrator(), function (Grid $grid) {
$grid->column('id');
$grid->column('username');
$grid->column('name');
$grid->column('created_at');
$grid->column('updated_at');
// 指定行选择器选中时显示的值的字段名称
// 指定行选择器选中时显示的值的字段名称
// 指定行选择器选中时显示的值的字段名称
// 如果表格数据中带有 “name”、“title”或“username”字段,则可以不用设置
$grid->rowSelector()->titleColumn('username');
$grid->quickSearch(['id', 'username', 'name']);
$grid->paginate(10);
$grid->disableActions();
$grid->filter(function (Grid\Filter $filter) {
$filter->like('username')->width(4);
$filter->like('name')->width(4);
});
});
}
}
多图和多文件上传
多图 / 文件上传的时候提交的数据是一个 array
数组,你可以通过以下方式把数据在保存进数据库之前改为你想要的格式:
// 转化为json格式保存到数据库
$form->multipleFile($column[, $label])->saving(function ($paths) {
// 可以转化为由 , 隔开的字符串格式
// return implode(',', $paths);
// 也可以转化为json
return json_encode($paths);
});
JSON 格式字段处理
dcat-admin
的表单提供了下面几个组件来处理 JSON
格式的字段,方便用来处理 JOSN
格式的对象、一维数组、二维数组等对象。
键值对象 (keyValue)
如果你的字段存储的是不固定键
的 {"field":"value"}
格式,可以用 keyValue
组件:
$form->keyValue('column_name');
// 设置校验规则
$form->keyValue('column_name')->rules('required|min:5');
一维数组 (list)
如果你的字段是用来存储 ["foo", "Bar"]
格式的一维数组,可以使用 list
组件:
$form->list('column_name');
// 设置校验规则
$form->list('column_name')->rules('required|min:5');
// 设置最大和最小元素个数
$form->list('column_name')->max(10)->min(5);
二维数组 (table)
如果某一个字段存储的是 json
格式的二维数组,可以使用 table
表单组件来实现快速的编辑:
$form->table('column_name', function ($table) {
$table->text('key');
$table->text('value');
$table->text('desc');
})->saving(function ($v) {
return json_encode($v);
});
这个组件类似于 hasMany
组件,不过是用来处理单个字段的情况,适用于简单的二维数据。
二维数组 (array)
如果某一个字段存储的是 json
格式的二维数组,并且字段比较多,可以使用 array
表单组件来实现快速的编辑:
$form->array('column_name', function ($table) {
$table->text('key');
$table->text('value');
$table->textarea('desc');
})->saveAsJson();
表单验证
$form->text('title')->rules('required|min:3');
// 复杂的验证规则可以在回调里面实现
$form->text('title')->rules(function (Form $form) {
// 如果不是编辑状态,则添加字段唯一验证
if (!$id = $form->model()->id) {
return 'unique:users,email_address';
}
});
也可以给验证规则自定义错误提示消息:
$form->text('code')->rules('required|regex:/^\d+$/|min:10', [
'regex' => 'code必须全部为数字',
'min' => 'code不能少于10个字符',
]);
表单布局
多列布局 (column)
左右两列布局方式,可以参考下面的代码来实现
// 第一列占据1/2的页面宽度
$form->column(6, function (Form $form) {
$form->text('name')->required();
$form->date('born')->required();
$form->select('education')->options([...])->required();
$form->text('nation')->required();
$form->text('native')->required();
$form->text('job')->required();
$form->text('code')->required();
$form->text('phone')->required();
$form->text('work')->required();
$form->text('census')->required();
});
// 第二列占据1/2的页面宽度
$form->column(6, function (Form $form) {
$form->image('avatar');
$form->decimal('wages');
$form->decimal('fund');
$form->decimal('pension');
$form->decimal('fee');
$form->decimal('business');
$form->decimal('other');
$form->text('area')->default(0);
$form->textarea('illness');
$form->textarea('comment');
});
// 调整所有表单的宽度
$form->width(9, 2);
以上布局功能使用了 bootstrap
的栅格布局系统,所有列的宽度总和不得超出 12
,并且也支持在 hasMany
和 array
表单中使用
$form->hasMany('jobs', function ($form) {
$form->column(6, function (Form $form) {
$form->text('name')->required();
$form->date('born')->required();
});
$form->column(6, function (Form $form) {
$form->image('avatar');
$form->decimal('wages');
});
});
多行布局 (row)
使用
$form->row(function (Form\Row $form) {
$form->width(4)->text('username')->required();
$form->width(3)->text('title');
...
});
$form->row(function (Form\Row $form) {
...
});
...
并且也支持在 hasMany
和 array
表单中使用
$form->hasMany('jobs', function ($form) {
$form->row(function (Form\Row $form) {
...
});
$form->row(function (Form\Row $form) {
...
});
});
选项卡表单 (tab)
如果表单元素太多,会导致表单页面太长,这种情况下可以使用 tab
方法来分隔表单:
$form->tab('Basic info', function (Form $form) {
$form->text('username');
$form->email('email');
})->tab('Profile', function (Form $form) {
$form->image('avatar');
$form->text('address');
$form->mobile('phone');
})->tab('Jobs', function (Form $form) {
$form->hasMany('jobs', function ($form) {
$form->text('company');
$form->date('start_date');
$form->date('end_date');
});
})
同时,tab
布局中也允许嵌套使用 column
和 row
布局
$form->tab('Basic info', function (Form $form) {
$form->column(6, function (Form\BlockForm $form) {
$form->display('id');
$form->text('name');
});
$form->column(6, function (Form\BlockForm $form) {
$form->text('username');
});
})
分块布局 (block)
如果你的表单中字段非常多,那么可以通过以下方式让你的表单分块布局,并且允许嵌套使用 column
和 row
布局
$form->block(8, function (Form\BlockForm $form) {
// 设置标题
$form->title('基本设置');
// 显示底部提交按钮
$form->showFooter();
// 设置字段宽度
$form->width(9, 2);
$form->column(6, function (Form\BlockForm $form) {
$form->display('id');
$form->text('name');
$form->email('email');
$form->image('avatar');
$form->password('password');
});
$form->column(6, function (Form\BlockForm $form) {
$form->text('username');
$form->email('mobile');
$form->textarea('description');
});
});
$form->block(4, function (Form\BlockForm $form) {
$form->title('分块2');
$form->text('nickname');
$form->number('age');
$form->radio('status')->options(['1' => '默认', 2 => '冻结'])->default(1);
$form->next(function (Form\BlockForm $form) {
$form->title('分块3');
$form->date('birthday');
$form->date('created_at');
});
});
表单字段动态显示
表单字段动态显示是指,在选择表单项的指定的选项时,联动显示其他的表单项。
目前支持的表单联动的组件有:
- select
- multipleSelect
- radio
- checkbox
使用方法
可以将上面的组件分为单选和多选两种类型,其中 select、radio 为单选组件,其它为多选组件
单选组件
下面的例子中,选择不同的国籍类型,将会切换选择不同的联动表单项:
$form->radio('radio')
->when([1, 4], function (Form $form) {
// 值为1和4时显示文本框
$form->text('text1');
$form->text('text2');
$form->text('text3');
})
->when(2, function (Form $form) {
$form->editor('editor');
})
->when(3, function (Form $form) {
$form->image('image');
})
->options([
1 => '显示文本框',
2 => '显示编辑器',
3 => '显示文件上传',
4 => '还是显示文本框',
])
->default(1);
上例中,方法 when(1, $callback) 等效于 when('=', 1, $callback), 如果用操作符 =,则可以省略这个参数
同时也支持这些操作符,=、>、>=、<、<=、!= 使用方法如下:
$form->radio('check')
->when('>', 1, function () {
})->when('>=', 2, function () {
});
select
组件的使用方法和 radio
是一样的。
多选组件
$form->checkbox('nationality', '国籍')
->options([
1 => '中国',
2 => '外国',
])->when([1, 2], function (Form $form) {
$form->text('name', '姓名');
$form->text('idcard', '身份证');
})->when('notIn', 2, function (Form $form) {
$form->text('name', '姓名');
$form->text('passport', '护照');
});
multipleSelect
组件的使用方法和 checkbox
是一样的。
布局
表单动态显示功能支持结合 column
以及 tab
布局功能一起使用,用法如下
tab
布局
$form->tab('Radio', function (Form $form) {
$form->display('title')->value('单选框动态展示');
$form->radio('radio')
->when([1, 4], function (Form $form) {
$form->text('text1');
$form->text('text2');
})
->when(2, function (Form $form) {
$form->editor('editor');
})
->options($this->options)
->default(1);
});
column
布局
$form->column(6, function (Form $form) {
$form->radio('radio')
->when([1, 4], function (Form $form) {
$form->text('text1');
$form->text('text2');
})
->when(2, function (Form $form) {
$form->editor('editor');
})
->options($this->options)
->default(1);
});
数据详情
修改显示内容
用下面的方法修改显示内容
$show->title()->as(function ($title) {
// 获取当前行的其他字段
$username = $this->username;
return "<{$title}> {$username}";
});
$show->contents()->as(function ($content) {
return "<pre>{$content}</pre>";
});
view
view
方法可以引入一个视图文件。
// 模板中接收以下三个变量:
// name 字段名称
// value 字段值
// model 当前行数据
$show->content->view('admin.fields.content');
explode
explode
方法可以把字符串分割为数组。
$show->tag->explode()->label();
// 可以指定分隔符,默认","
$show->tag->explode('|')->label();
image
字段 avatar 的内容是图片的路径或者 url,可以将它显示为图片:
$show->avatar()->image();
file
字段 document 的内容是文件的路径或者 url,可以将它显示为文件:
$show->avatar()->file();
label
将字段 tag 的内容显示为 label:
$show->tag()->label();
badge
将字段 rate 的内容显示为 badge:
$show->rate()->badge();
dot
通过 dot
方法可以在列文字前面加上一个带颜色的圆点
use Dcat\Admin\Admin;
$show->state
->using([1 => '未处理', 2 => '已处理', ...])
->dot(
[
1 => 'primary',
2 => 'danger',
3 => 'success',
4 => Admin::color()->info(),
],
'primary' // 第二个参数为默认值
);
显示文件尺寸
如果字段数据是表示文件大小的字节数,可以通过调用 filezise 方法来显示更有可读性的文字
$show->field('file_size')->filesize();
这样数值 199812019 将会显示为 190.56 MB
模型树
这个功能可以实现一个树状组件,可以用拖拽的方式实现数据的层级、排序等操作,下面是基本的用法。
表结构和模型
要使用 model-tree
,要遵守约定的表结构:
{tip}
parent_id
字段一定要默认为0
!!!
CREATE TABLE `demo_categories` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NOT NULL DEFAULT '0',
`order` int(11) NOT NULL DEFAULT '0',
`title` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
上面的表格结构里面有三个必要的字段 parent_id
、order
、title
, 其它字段没有要求。
对应的模型为 app/Models/Category.php
:
<?php
namespace App\Models\Demo;
use Dcat\Admin\Traits\ModelTree;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use ModelTree;
protected $table = 'demo_categories';
}
表结构中的三个字段 parent_id
、order
、title
的字段名也是可以修改的:
{tip} 为了便于阅读,这里不再展示
Repository
代码。
<?php
namespace App\Models\Demo;
use Dcat\Admin\Traits\ModelTree;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use ModelTree;
protected $table = 'demo_categories';
// 父级ID字段名称,默认值为 parent_id
protected $parentColumn = 'pid';
// 排序字段名称,默认值为 order
protected $orderColumn = 'sort';
// 标题字段名称,默认值为 title
protected $titleColumn = 'name';
}
使用方法
然后就是在页面中使用 model-tree
了:
<?php
namespace App\Admin\Controllers\Demo;
use App\Models\Category;
use Dcat\Admin\Layout\Row;
use Dcat\Admin\Layout\Content;
use Dcat\Admin\Tree;
use Dcat\Admin\Controllers\AdminController;
class CategoryController extends AdminController
{
public function index(Content $content)
{
return $content->header('树状模型')
->body(function (Row $row) {
$tree = new Tree(new Category);
$row->column(12, $tree);
});
}
}
可以通过下面的方式来修改行数据的显示:
$tree = new Tree(new Category);
$tree->branch(function ($branch) {
$src = config('admin.upload.host') . '/' . $branch['logo'] ;
$logo = "<img src='$src' style='max-width:30px;max-height:30px' class='img'/>";
return "{$branch['id']} - {$branch['title']} $logo";
});
在回调函数中返回的字符串类型数据,就是在树状组件中的每一行的显示内容,$branch
参数是当前行的数据数组。
修改模型查询条件
如果要修改模型的查询,用下面的方式
$tree->query(function ($model) {
return $model->where('type', 1);
});
限制最大层级数
默认 5
$tree->maxDepth(3);
自定义行操作
use Dcat\Admin\Tree;
$tree->actions(function (Tree\Actions $actions) {
if ($actions->row->id > 5) {
$actions->disableDelete(); // 禁用删除按钮
}
// 添加新的action
$actions->append(...);
});
// 批量添加action
$tree->actions([
new Action1(),
"<div>...</div>",
...
]);
开发工具
IDE 自动补全
通过 php artisan admin:ide-helper 命令可以生成 IDE 自动补全文件,可以生成 Grid、Form、Show 等功能的 IDE 自动补全提示文件。
代码生成器
代码生成器可以通过界面一键生成增删改查代码,支持根据已有数据表生成增删改查代码,打开浏览器访问 http://localhost:8000/admin/helpers/scaffold 即可使用。
如果你的开发环境不是 windows 系统,请给整个项目 777 权限,否则可能无法生成文件。
扩展包管理
Dcat Admin 支持可视化管理扩展包,只要通过 composer 安装进来的扩展包都能在管理界面中看到,支持通过界面启用和导入扩展包,打开浏览器访问 http://localhost:8000/admin/helpers/extensions 即可使用。