一、基本的数据插入操作
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)进行保护。
fillable 或 guarded 这两个属性分别用于定义哪些模型字段允许批量赋值以及哪些模型字段是受保护的,不能显式进行批量赋值。
如果模型中使用了 create() 方法,但又没有添加 fillable 或 guarded 属性,那么会报 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 可以关联多个 Phone,phones 表结构如下(通过 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 为 2 的 Role 之间的关联。
// 方法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']);
原文链接:https://www.hangge.com/blog/cache/detail_2390.html