各メソッドの挙動の違い
DB保存の方法はいくつかあるが、どういう違いがあるかを把握せずに使っていたため、主に使うcreate()
、save()
、insert()
の違いをまとめていく。
create()
指定された属性を持つ新しいモデルインスタンスを作成し、データベースに保存してからそのインスタンスを返す。
$user = User::create(['name' => 'hoge']);
vendorの中を見にいくと以下のようなコードが書かれている。
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php
/*
* Save a new model and return the instance.
*
* @param array $attributes
* @return \Illuminate\Database\Eloquent\Model|$this
*/
public function create(array $attributes = [])
{
return tap($this->newModelInstance($attributes), function ($instance) {
$instance->save();
});
}
save()
モデルのインスタンスをデータベースに保存する。create()
と異なり、保存後インスタンスは返さず、保存が成功したかどうかを示すブール値を返す。
また、モデルが既にデータベースに存在する場合(モデルがデータベースから取得された場合や、新しいレコードがデータベースに挿入された後等)は更新を行い、存在しない場合は新規保存を行う。
$user = new User();
$user->name = $request->name;
$user->save();
vendorの中を見にいくと以下のようなコードが書かれている。
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php
/*
* Save the model to the database.
*
* @param array $options
* @return bool
*/
public function save(array $options = [])
{
$query = $this->newModelQuery();
// If the "saving" event returns false we'll bail out of the save and return
// false, indicating that the save failed. This provides a chance for any
// listeners to cancel save operations if validations fail or whatever.
if ($this->fireModelEvent('saving') === false) {
return false;
}
// If the model already exists in the database we can just update our record
// that is already in this database using the current IDs in this "where"
// clause to only update this model. Otherwise, we'll just insert them.
if ($this->exists) {
$saved = $this->isDirty() ?
$this->performUpdate($query) : true;
}
// If the model is brand new, we'll insert it into our database and set the
// ID attribute on the model to the value of the newly inserted row's ID
// which is typically an auto-increment value managed by the database.
else {
$saved = $this->performInsert($query);
if (! $this->getConnectionName() &&
$connection = $query->getConnection()) {
$this->setConnection($connection->getName());
}
}
// If the model is successfully saved, we need to do a few more things once
// that is done. We will call the "saved" method here to run any actions
// we need to happen after a model gets successfully saved right here.
if ($saved) {
$this->finishSave($options);
}
return $saved;
}
insert()
複数のレコードを一度に保存する。直接SQLのINSERT文を実行するため、タイムスタンプの更新等は行わない。また、fillable
のチェックが行われないため、複数代入による脆弱性が発生する可能性もある。
User::insert([['name' => 'hoge']]);
vendorの中を見にいくと以下のようなコードが書かれている。
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php
/*
* Save a new model and return the instance.
*
* @param array $attributes
* @return \Illuminate\Database\Eloquent\Model|$this
*/
public function create(array $attributes = [])
{
return tap($this->newModelInstance($attributes), function ($instance) {
$instance->save();
});
}
まとめ
-
create()
:新しいモデルインスタンスを作成、データベースに保存してそのインスタンスを返す -
save()
:既存のモデルインスタンスをデータベースに保存する。新しいインスタンスを保存することも可能 -
insert()
:複数のレコードを一度に挿入する。fillable属性のチェックがされないので使い時に注意