Home » 未分类 » Laravel-admin使用心得

Laravel-admin使用心得

Laravel-admin是借助强大的Laravel框架,10分钟内搭建一个功能健全CRUD后台不是梦。入手一周,总结一些注意点如下。

修改内置视图资源

有时候想对内置的视图进行修改,参考官方文档的常见问题即可。

select联动多个

联动单个是load(),联动多个就是loads()。这点文档上没有,查看源代码可得知。

select联动的项编辑时如何填充

首先,如果填充这个表单项的资源是一个关联而不是一个字段,切忌不要将关联项的名跟字段名一致。如一件商品所属品牌,数据库中字段是category_id,那么商品模型中的关联就不要是category_id了,叫个category之类的就可以了,否则,laravel-admin在判断是否选中的时候,由于表单字段是category_id,通过模型访问category_id属性的时候,由于关联正好也是这个名字,就直接查询关联得出目标分类的数据了,然后在select中循环时,option的值是一个标量类型的值,字段的值是一个数组,不可能相等。

要填充,可以在options中传递一个函数,通过字段的值查询,只填充它一个的值到select中,如下:(注意模型关联中不要再叫bind_store)

$form->select('bind_store', '绑定门店')
  ->options(function ($id) {
      $store = Store::find($id);
      if ($store)
      {
          return [$store->id => $store->name];
      }
  });

Checkbox/MultipleSelect多对多关联编辑时无法选中

遇到这种情况(比如这个issue)很有可能是关联名使用了驼峰式(camel)命名法,调整为下划线(snake)即可。我是通过查看edit()方法追到setFieldValue()那里,打印$data发现关联取回来时字段名是使用下划线的方式命名的。查看该文件的blame发现,很有可能是会导致其他bug从而去掉了恢复原始关联名的那个转换。因此,对于关联名还是当作字段一样看待,尽量使用下划线的方式命名吧。(Update: 这个可能是bug,随着版本更新可能已经修复)

2018-11-27 补充:这个问题一直存在,对于要在表单中使用的关联,请使用下划线方式命名,否则编辑时候无法填充。  

表单中一对一关联

一对一关联,可以直接嵌套在基本表单项中,见文档。假如有$form->text(‘admin.name’),提交过来时候数据是$form->admin[‘name’],注意$form->admin是数组,不是对象。另外,在saving回调中,若要修改关联的值,如$form->admin[‘password’] = bcrypt($form->admin[‘password’]),这样子是会报错“Indirect modification of overloaded property”错误,正确的写法是先用一个变量保存$form->admin,然后修改其password,再将整个值赋予$form。再者,在saved回调中,关联是不会有值的,如例子中$form->model()->admin值将是null,虽然它会正确将admin关联数据添加到数据库中,但并不将结果关联到模型中,需要手工再查找,如:$form->model()->admin()->firstOrFail()->roles()->save(Role::agent()->firstOrFail())。

表单回调顺序

关于表单回调,它的顺序是在 Laravel 自带的模型事件之后,自带的模型事件要先!!!这个要注意,当有关联要处理时,最好在它的表单回调中处理,在自带的模型事件中可能关联字段没有值。

select如何禁止修改

要为select设置disabled,这是添加 js 插件 select2 添加配置参数,使用config($key, $val)的形式进行设置,注意不支持传递数组,设置多个调用多次。如:

$form->select($foreignKey, '抽奖')->options([$luckyDraw->id => $luckyDraw->title])
    ->value($luckyDraw->id)->readOnly()->config('disabled', true);

关于表单中的关联

当涉及到多图时,增删一张尤其麻烦,所以尽量使用自带封装好的功能,不要重写store/update方法,有多余操作可以在saving/saved回调中做,注意saving回调中不能添原先没有的字段,因此可以先给个默认值,然后修改之。关联只有一对一关联才可以直接在表单中使用,当是一对多时,看能否给一个额外的关联变成一对一,这样就可以直接使用。如发帖,帖子的回复理论是一对多,但发帖时只要录入1楼的数据,其实是一对一。代码参考:


//model
public function comments()
{
    return $this->morphMany(Comment::class, "target");
}

public function first_comment()
{
    return $this->hasOne(Comment::class, "target_id")
        ->where('target_type', __CLASS__)
        ->where('floor_num', 1);
}
//form
protected function form()
{
    $form = new Form(new Topic);
    $form->select('type', '类型')->options(Topic::$typeNames);
    $form->hidden('uid', 'uid')->value(0);
    $form->multipleImage('first_comment.images', '配图')->removable()->uniqueName();
    $form->editor('first_comment.content', '内容文本');
    $form->hidden('first_comment.uid', 'uid')->value(0);
    $form->hidden('first_comment.target_type', 'target_type')->value(Topic::class);
    $form->hidden('first_comment.floor_num', 'floor_num')->value(1);

    $form->saving(function ($form) {
        $admin = \Admin::user();
        $user = $admin->frontUser;
        if (!$user) {
            $error = new MessageBag(['title' => '业务错误', 'message' => '没有绑定前端用户,不能发帖']);
            return back()->with(compact('error'));
        }
        $form->uid = $user->id;
        $firstComment = $form->first_comment;
        $firstComment['uid'] = $user->id;
        $form->first_comment = $firstComment;
    });

    return $form;
}

自定义中间表时间字段

在belongsToMany()关联中,可以通过withTimestamps($createdAt, $updatedAt)设置关联表的时间字段名称,但是如果要想进一步控制格式,就要使用using()方法指定模型了。定义关联的时候一调用withTimestamps()就得 created_at 和 updated_at 两个都有,因此中间表也是两个字段都得有。而且即使使用了using(),定义关联时的参数2中间表名也还是需要写的。

public function productlines()
{
    return $this->belongsToMany(Productline::class, 'hawk_pdlmember', 'userId', 'productlineId')
        ->using(ProductLineMember::class)
        ->withTimestamps('addTime', 'updateTime');
}

dd

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Time limit is exhausted. Please reload CAPTCHA.