Laravel-admin 创建美观的树形无限极分类视图


版本说明

  • laravel/framework: 5.5.*
  • encore/laravel-admin: ^1.7

表和模型

  • 表结构没啥好说的,其定义如下:
字段名称    字段类型    字段描述
id    unsigned int primary key    自增主键
pid    unsigned int    父级分类ID
cate_name    varchar(30)    分类名称
sort    unsigned smallint    排序字段
  • CategoriesModel.php的定义:
<?php
 
 
namespace App\Models;
 
 
use Encore\Admin\Traits\AdminBuilder;
use Encore\Admin\Traits\ModelTree;
use Illuminate\Database\Eloquent\Model;
 
class CategoriesModel extends Model
{
    use ModelTree, AdminBuilder;
    protected $table = 'categories';
 
    protected $fillable = ['pid', 'cate_name', 'sort'];
 
    protected $with = [
        'parent'
    ];
 
 
    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);
        $this->setParentColumn('pid');  // 父ID
        $this->setOrderColumn('sort'); // 排序
        $this->setTitleColumn('cate_name'); // 标题
    }
 
 
    // 该分类下的品牌
    public function brand()
    {
        return $this->hasMany(BrandModel::class, 'cate_id', $this->getKeyName());
    }
 
 
    /**
     * 该分类的子分类
     */
    public function child()
    {
        return $this->hasMany(get_class($this), 'pid', $this->getKeyName());
    }
 
    /**
     * 该分类的父分类
     */
    public function parent()
    {
        return $this->hasOne(get_class($this), $this->getKeyName(), 'pid');
    }
}

使用了两个trait: ModelTreeAdminBuilder方便构造树形结构数据。

需要注意的是在定义表结构时,需要存在parent_id, order, title字段,当然意义上跟其一致即可,名称可以随意定义,可以在构造方法中设置对应字段的名称。

 

控制器定义

  • 通过 php artisan admin:make CategoriesController --model=App\Models\CategoriesModel生成控制器。

    发现CategoriesController是默认继承AdminController类的,点进去看AdminController类的定义如下:

<?php
 
namespace Encore\Admin\Controllers;
 
use Encore\Admin\Layout\Content;
use Illuminate\Routing\Controller;
 
class AdminController extends Controller
{
    use HasResourceActions;
 
    /**
     * Title for current resource.
     *
     * @var string
     */
    protected $title = 'Title';
 
    /**
     * Set description for following 4 action pages.
     *
     * @var array
     */
    protected $description = [
//        'index'  => 'Index',
//        'show'   => 'Show',
//        'edit'   => 'Edit',
//        'create' => 'Create',
    ];
 
    /**
     * Get content title.
     *
     * @return string
     */
    protected function title()
    {
        return $this->title;
    }
 
    /**
     * Index interface.
     *
     * @param Content $content
     *
     * @return Content
     */
    public function index(Content $content)
    {
        return $content
            ->title($this->title())
            ->description($this->description['index'] ?? trans('admin.list'))
            ->body($this->grid());
    }
 
    /**
     * Show interface.
     *
     * @param mixed   $id
     * @param Content $content
     *
     * @return Content
     */
    public function show($id, Content $content)
    {
        return $content
            ->title($this->title())
            ->description($this->description['show'] ?? trans('admin.show'))
            ->body($this->detail($id));
    }
 
    /**
     * Edit interface.
     *
     * @param mixed   $id
     * @param Content $content
     *
     * @return Content
     */
    public function edit($id, Content $content)
    {
        return $content
            ->title($this->title())
            ->description($this->description['edit'] ?? trans('admin.edit'))
            ->body($this->form()->edit($id));
    }
 
    /**
     * Create interface.
     *
     * @param Content $content
     *
     * @return Content
     */
    public function create(Content $content)
    {
        return $content
            ->title($this->title())
            ->description($this->description['create'] ?? trans('admin.create'))
            ->body($this->form());
    }
}
 
  • AdminController控制器使用了一个trait:HasResourceActions,还有就是对index丶show丶edit丶create操作的封装。点击HasResourceActions,看其定义:
trait HasResourceActions
{
    /**
     * Update the specified resource in storage.
     *
     * @param int $id
     *
     * @return \Illuminate\Http\Response
     */
    public function update($id)
    {
        return $this->form()->update($id);
    }
 
    /**
     * Store a newly created resource in storage.
     *
     * @return mixed
     */
    public function store()
    {
        return $this->form()->store();
    }
 
    /**
     * Remove the specified resource from storage.
     *
     * @param int $id
     *
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        return $this->form()->destroy($id);
    }
}

发现Trait:HasResourceActions是对store丶destroy丶update的封装,类中只有定义了form方法即可实现三种操作。

那么我们的分类控制器:Categories可以通过继承基本的Controller和使用trait:HasResourceActions来实现树形图的操作, CategoriesController.php代码如下:

<?php
 
namespace App\Admin\Controllers;
 
use App\Models\CategoriesModel;
use Encore\Admin\Controllers\HasResourceActions;
use Encore\Admin\Layout\{Column, Row, Content};
use Encore\Admin\{Tree,Form};
use Encore\Admin\Widgets\Box;
use Illuminate\Http\RedirectResponse;
 
 
/**
 * 分类管理
 * @package App\Admin\Controllers
 */
class CategoriesController extends Content
{
    use HasResourceActions;
 
    protected $title = '分类';
 
    /**
     * 首页
     * @param Content $content
     * @return Content
     */
    public function index(Content $content)
    {
        return $content->title('分类')
            ->description('列表')
            ->row(function (Row $row){
                // 显示分类树状图
                $row->column(6, $this->treeView()->render());
 
                $row->column(6, function (Column $column){
                    $form = new \Encore\Admin\Widgets\Form();
                    $form->action(admin_url('categories'));
                    $form->select('pid', __('Parent Category'))->options(CategoriesModel::selectOptions());
                    $form->text('cate_name', __('Category Name'))->required();
                    $form->number('sort', __('Asc Sort'))->default(99)->help('越小越靠前');
                    $form->hidden('_token')->default(csrf_token());
                    $column->append((new Box(__('category.new'), $form))->style('success'));
                });
 
            });
    }
 
 
    /**
     * 树状视图
     * @return Tree
     */
    protected function treeView()
    {
        return  CategoriesModel::tree(function (Tree $tree){
            $tree->disableCreate(); // 关闭新增按钮
            $tree->branch(function ($branch) {
                return "<strong>{$branch['cate_name']}</strong>"; // 标题添加strong标签
            });
        });
    }
 
    /**
     * 详情页
     * @param $id
     * @return RedirectResponse
     */
    public function show($id)
    {
        return redirect()->route('categories', ['id' => $id]);
    }
 
    /**
     * 编辑
     * @param $id
     * @param Content $content
     * @return Content
     */
    public function edit($id, Content $content)
    {
        return $content->title(__('Categories'))
            ->description(__('edit'))
            ->row($this->form()->edit($id));
    }
 
 
    /**
     * 表单
     * @return Form
     */
    public function form()
    {
        $form = new Form(new CategoriesModel());
 
        $form->display('id', 'ID');
        $form->select('pid', __('Parent Category'))->options(CategoriesModel::selectOptions());
        $form->text('cate_name', __('Category Name'))->required();
        $form->number('sort', __('Asc Sort'))->default(99)->help('越小越靠前');
        return $form;
    }
 
}
 
  • 需要注意的是index方法中的Form和form方法中的form是不同的。
  • CategoriesModel::selectOptions()方法可以快捷的列出可选项包括默认值0。

实现效果图

  • 首页(左边是所有分类,右边是快捷创建分类。)

 

 

  • 编辑页

 

 


版权声明:本文为CSDN博主「ClassmateLin」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ClassmateLin/article/details/104324581

 

 

 

 

 

 

 

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM