插入 & 更新关联模型
保存方法
Eloquent 为新模型添加关联提供了便捷的方法。例如,也许你需要添加一个新的 Comment 到一个 Post 模型中。你不用在 Comment 中手动设置 post_id 属性,就可以直接使用关联模型的 save 方法将 Comment 直接插入:$comment = new App\Comment(['message' => 'A new comment.']);$post = App\Post::find(1);$post->comments()->save($comment);
需要注意的是,我们并没有使用动态属性的方式访问 comments 关联。相反,我们调用 comments 方法来获得关联实例。save 方法将自动添加适当的 post_id 值到 Comment 模型中。
如果你需要保存多个关联模型,你可以使用 saveMany 方法:$post = App\Post::find(1);$post->comments()->saveMany([ new App\Comment(['message' => 'A new comment.']), new App\Comment(['message' => 'Another comment.']),]);
新增方法
除了 save 和 saveMany 方法外,你还可以使用 create 方法。它接受一个属性数组,同时会创建模型并插入到数据库中。 还有, save 方法和 create 方法的不同之处在于, save 方法接受一个完整的 Eloquent 模型实例,而 create 则接受普通的 PHP 数组:$post = App\Post::find(1);$comment = $post->comments()->create([ 'message' => 'A new comment.',]);
你还可以使用 createMany 方法去创建多个关联模型:$post = App\Post::find(1);$post->comments()->createMany([ [ 'message' => 'A new comment.', ], [ 'message' => 'Another new comment.', ],]);
更新 belongsTo 关联
当更新 belongsTo 关联时,可以使用 associate 方法。此方法将会在子模型中设置外键:$account = App\Account::find(10);$user->account()->associate($account);$user->save();
当移除 belongsTo 关联时,可以使用 dissociate 方法。此方法会将关联外键设置为 null:$user->account()->dissociate();$user->save();
多对多关联
附加 / 分离
Eloquent 也提供了一些额外的辅助方法,使相关模型的使用更加方便。例如,我们假设一个用户可以拥有多个角色,并且每个角色都可以被多个用户共享。给某个用户附加一个角色是通过向中间表插入一条记录实现的,可以使用 attach 方法完成该操作:$user = App\User::find(1);$user->roles()->attach($roleId);
在将关系附加到模型时,还可以传递一组要插入到中间表中的附加数据:$user->roles()->attach($roleId, ['expires' => $expires]);
当然,有时也需要移除用户的角色。可以使用 detach 移除多对多关联记录。detach 方法将会移除中间表对应的记录;但是这 2 个模型都将会保留在数据库中:// 移除用户的一个角色...$user->roles()->detach($roleId);// 移除用户的所有角色...$user->roles()->detach();
为了方便,attach 和 detach 也允许传递一个 ID 数组:$user = App\User::find(1);$user->roles()->detach([1, 2, 3]);$user->roles()->attach([ 1 => ['expires' => $expires], 2 => ['expires' => $expires]]);
同步关联
你也可以使用 sync 方法构建多对多关联。sync 方法接收一个 ID 数组以替换中间表的记录。中间表记录中,所有未在 ID 数组中的记录都将会被移除。所以该操作结束后,只有给出数组的 ID 会被保留在中间表中:$user->roles()->sync([1, 2, 3]);
你也可以通过 ID 传递额外的附加数据到中间表:$user->roles()->sync([1 => ['expires' => true], 2, 3]);
如果你不想移除现有的 ID,可以使用 syncWithoutDetaching 方法:$user->roles()->syncWithoutDetaching([1, 2, 3]);
切换关联
多对多关联也提供了 toggle 方法用于「切换」给定 ID 数组的附加状态。 如果给定的 ID 已被附加在中间表中,那么它将会被移除,同样,如果如果给定的 ID 已被移除,它将会被附加:$user->roles()->toggle([1, 2, 3]);
在中间表上保存额外的数据
当处理多对多关联时,save 方法接收一个额外的数据数组作为第二个参数App\User::find(1)->roles()->save($role, ['expires' => $expires]);
更新中间表记录
如果你需要在中间表中更新一条已存在的记录,可以使用 updateExistingPivot 。此方法接收中间表的外键与要更新的数据数组进行更新:$user = App\User::find(1);$user->roles()->updateExistingPivot($roleId, $attributes);
更新父级时间戳
当一个模型属 belongsTo 或者 belongsToMany 另一个模型时, 例如 Comment 属于 Post,有时更新子模型导致更新父模型时间戳非常有用。例如,当 Comment 模型被更新时,您要自动「触发」父级 Post 模型的 updated_at 时间戳的更新。Eloquent 让它变得简单。只要在子模型加一个包含关联名称的 touches 属性即可:<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Comment extends Model{ /** * 要触发的所有关联关系。 * * @var array */ protected $touches = ['post']; /** * 评论所属文章。 */ public function post() { return $this->belongsTo('App\Post'); }}
现在,当你更新一个 Comment 时,对应父级 Post 模型的 updated_at 字段也会被同时更新,使其更方便得知何时让一个 Post 模型的缓存失效:$comment = App\Comment::find(1);$comment->text = 'Edit to this comment!';$comment->save();
看完本文有收获?点赞、分享是最大的支持!