返回 导航

其他

hangge.com

Laravel - MySQL数据库的使用详解7(Eloquent ORM用法4:插入、更新数据)

作者:hangge | 2019-05-27 08:10

一、基本的数据插入操作

1,插入数据

(1)想要在数据库中插入新的记录,只需创建一个新的模型实例,设置模型的属性,然后调用 save 方法即可:
注意created_at updated_at 时间戳在 save 方法被调用时会自动被设置,如果我们数据表中没有定义这两个字段,可以在模型中将自动时间戳功能关闭。具体参考我之前的文章
$User = new User;
$User->username = "测试用户";
$User->age = 111;
$User->save();

(2)查看数据库可以看到数据已经新增成功了。

2,使用批量赋值插入数据

(1)我们还可以使用 create 方法保存一个新的模型。该方法返回被插入的模型实例。
$user = User::create([
'username'=>'刘大哥',
'age'=>'3'
]);

(2)但是,在此之前,我们需要指定模型的 fillable guarded 属性,因为所有 Eloquent 模型都通过批量赋值(Mass Assignment)进行保护。
批量赋值(Mass Assignment)保护的作用:
批量赋值功能常常用来将提交过来的表单数据写入数据库,比如下面 $request 是表单或者 url 参数提交过来的数据:
  • $user = User::create($request);
但如果恶意用户通过 HTTP 请求发送一个 is_admin 参数,然后该参数映射到模型的 create 方法,从而允许用户将自己变成管理员,这就出现了安全问题。

(3)如果我们需要定义哪些属性是可以进行赋值的,使用模型上的 $fillable 属性即可(白名单)。
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model {
  
  /**
  * 可以被批量赋值的属性.
  *
  * @var array
  */
  protected $fillable = ['username', 'age'];
}

(4)而 $guarded 功能正好相反,该包含你不想被赋值的属性数组(黑名单),不被包含在其中的属性都是可以被赋值的。
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model {
  
  /**
   * 不能被批量赋值的属性
   *
   * @var array
   */
  protected $guarded = ['is_admin'];
}

3,先查询再插入(firstOrCreate)

firstOrCreate 方法先尝试通过给定列/值对在数据库中查找记录,如果没有找到的话则通过给定属性创建一个新的记录。
// 通过属性获取用户, 如果不存在则创建。
$user = User::firstOrCreate(['username' => 'hangge']);

// 通过username属性获取用户,如果不存在则通过username和age属性创建。
$user = User::firstOrCreate(
    ['username' => 'hangge'], ['age' => 88]
);

4,先查询再创建模型实例(firstOrNew)

firstOrNew 方法和 firstOrCreate 方法一样先尝试在数据库中查找匹配的记录,如果没有找到,则返回一个新的模型实例。
注意:通过 firstOrNew 方法返回的模型实例并没有持久化到数据库中,我们还需要调用 save 方法手动持久化。
// 通过属性获取用户, 如果不存在初始化一个新的实例。
$user = User::firstOrNew(['username' => 'hangge']);

// 通过username属性获取用户,如果不存在则通过username和age属性创建新实例。
$user = User::firstOrNew(
    ['username' => 'hangge'], ['age' => 88]
);

二、基本的数据更新操作

1,更新数据

save 方法还可以用于更新数据库中已存在的模型。要更新一个模型,应该先获取它,设置你想要更新的属性,然后调用 save 方法。
注意:同 updated_at 时间戳会在更新时自动被设置,如果我们数据表中没有定义这个字段,可以在模型中将自动时间戳功能关闭。具体参考我之前的文章
$User = User::find(1);
$User->age = 999;
$User->save();

2,批量更新

使用 update 方法可以同时修改给定查询提供的多个模型实例。该要求以数组形式传递键值对参数,代表着数据表中应该被更新的列。
注意:通过 Eloquent 进行批量更新时,saved updated 模型事件将不会在更新模型时触发。这是因为在进行批量更新时并没有从数据库获取模型。
User::where('id', '>', 2)
      ->update(['age' => 0]);

3,存在则更新,不存在则插入(updateOrCreate)

如果碰到如果模型已存在则更新,否则创建新模型的场景,可以使用 updateOrCreate 方法。
注意:和 firstOrCreate 方法一样,updateOrCreate 方法会持久化模型,所以无需调用 save()
// 如果有从奥克兰到圣地亚哥的航班则将价格设置为 $99
// 如果没有匹配的模型则创建之
$flight = Flight::updateOrCreate(
    ['departure' => 'Oakland', 'destination' => 'San Diego'],
    ['price' => 99]
);

三、新增一对一、一对多关联模型

    这里以用户(User)和电话(Phone)为例,一个 User 可以关联多个 Phonephones 表结构如下(通过 user_id 关联 user 表的主键):

1,新增关联模型

我们常常会需要加入新的关联模型。如果想新增一个 phone 到某个 user 上,除了手动设定模型的 user_id 外键,还可以从上层的 User 模型新增关联的 phone
$phone = new Phone(['number' => '16890908888']);
$user = User::find(1);
$phone = $user->phones()->save($phone);

2,设置从属关联模型 ( belongsTo)

要更新 belongsTo 关联时,可以使用 associate 方法。这个方法会设定子模型的外键:
//下面将id为2的电话关联到id为1的用户上 
$user = User::find(1);
$phone = Phone::find(2);
$phone->user()->associate($user);
$phone->save();

四、新增多对多关联模型 (Many To Many)

    这里同样以用户、角色之间的相互关联为例:一个用户(user)可能用有很多角色(role),而一种角色可能很多用户都有。
    所以数据库会存在如下三个表:用户表(users)、角色表(roles)、用户角色关联表(role_user)。其中关联表以关联的两个模型命名(先后按字母顺序排列),关联表结构如下: 

1,新增关联表数据(单条)

(1)我们可以使用 attach 方法简单地把 role 附加给一个 user,就会自动在关联表中插入一条数据。下面代码两种方式结果都一样:
    新增 id 1 User id 2Role 之间的关联。
// 方法1
$user = User::find(1);
$user->roles()->attach(2);


// 方法1
$user = User::find(1);
$role = Role::find(2);
$user->roles()->attach($role);

(2)如果关联表额外的字段数据需要添加,可以在 attach 方法的第二个参数中传入要存在枢纽表中的属性数组。
$user = User::find(1);
$user->roles()->attach(2, ['expires' => 123456]);

2,新增关联表数据(多条)

(1)attach 方法也可以传入一个数组,同时在关联表中插入多个关联数据。
$user = User::find(1);
$user->roles()->attach([1 , 2, 3]);

(2)当然如果关联表额外的字段数据需要添加,我们添加多个关联数据时也可以附带上额外字段数据。
$user = User::find(1);
$user->roles()->attach([1 => ['expires' => 'value1'], 2 => ['expires' => 'value2']]);

3,删除关联表数据

(1)detach 方法功能与上面的 attach 方法正好相反,可以移除关联表中的关联数据。
$user = User::find(1);
$user->roles()->detach(1);

(2) detach 同样可以接受 ID 数组作为参数,同时删除关联表中的多条关联数据。
$user = User::find(1);
$user->roles()->detach([1, 2, 3]);

4,同步关联表数据

(1)sync 方法可以传入一个 ID 数组将关联数据同步到关联表中。与 attach 方法不同的是。sync 方法执行后,关联表只会保留数组参数中存在的关联数据,原有的关联数据如果不在这个数组参数中则会自动删除。
$user = User::find(1);
$user->roles()->sync([1, 2]);

  • 上面代码执行后,关联表的数据如下:

(2)当然如果关联表额外的字段数据需要添加,sync 方法同样支持附带上额外字段数据。
$user = User::find(1);
$user->roles()->sync([1 => ['expires' => 'value1'], 2]);

5,同时添加关联数据、及模型数据

(1)上面样例我们都是在模型数据存在的情况下,在关联表中添加相应的关联数据。我们也可以使用 save 方法同时插入关联数据以及模型数据。
    比如下面代码执行后,会自动在 role 表中添加一个新的角色(版主),并且在关联表中添加这个角色与 id 1 的用户关联。
$user = User::find(1);
$role = new Role(['rolename' => '版主']);
$user->roles()->save($role);

(2)当然如果关联表额外的字段数据需要添加,save 方法同样支持附带上额外字段数据。
$user = User::find(1);
$role = new Role(['rolename' => '版主']);
$user->roles()->save($role, ['expires' => 'value1']);
评论

全部评论(0)

回到顶部