$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]));
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

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,并且也支持在 hasManyarray 表单中使用

$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) {

并且也支持在 hasManyarray 表单中使用

$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 布局中也允许嵌套使用 columnrow 布局

$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)

如果你的表单中字段非常多,那么可以通过以下方式让你的表单分块布局,并且允许嵌套使用 columnrow 布局

$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 方法可以引入一个视图文件。

    // 模板中接收以下三个变量:
    // 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();
    

    字段 document 的内容是文件的路径或者 url,可以将它显示为文件:

    $show->avatar()->file();
    

    label

    将字段 tag 的内容显示为 label:

    $show->tag()->label();
    

    badge

    将字段 rate 的内容显示为 badge:

    $show->rate()->badge();
    

    通过 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_idordertitle, 其它字段没有要求。

    对应的模型为 app/Models/Category.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_idordertitle 的字段名也是可以修改的:

    {tip} 为了便于阅读,这里不再展示 Repository 代码。

    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 了:

    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);
    

    限制最大层级数

    $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 即可使用。