2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Laravel】DBデータ挿入(save, create, insert)

Last updated at Posted at 2024-07-16

追記 2024/7/19

@pop-culture-studio様よりコメントでご享受いただき修正。

先に結論

create()メソッドが記述量が少なく、複数代入から保護できる!
fill()->save()メソッドはコード量で難あり!(挿入ではなく、更新で使用)
insert()メソッドはセキュリティ面で難あり!(使わない)

Illuminate\Database\Eloquent\Builder
Illuminate\Database\Query\Builderの違い

この記事について

  • Laravel初学者向け
  • 今までDB挿入メソッドがごっちゃになっていた人

動作環境・使用するツールや言語

  • OS バージョン
      Windows11
  • ツール
      VSCode
  • フレームワーク
      Laravel8

前提として今回の簡単なマイグレーションファイルとモデル

create_tests_table.php
    public function up()
    {
        Schema::create('tests', function (Blueprint $table) {
            $table->id();
            $table->string('name', 255);
            $table->timestamps();
        });
    }
Test.php
    protected $guarded = [
        'id'
    ];

    protected $fillable = [
        'name'
    ];
  • $guarded
    Eloquentで書き換え不可能
  • $fillable
    Eloquentで書き換え可能
web.php
Route::get('/save', [TestController::class, 'save']);
Route::get('/create', [TestController::class, 'create']);
Route::get('/insert', [TestController::class, 'insert']);

create()メソッド

TestController.php
public function create()
    {
        Test::create([
            'name' => 'CreateExample',
        ]);
    }

この状態で/createにアクセスし、DBを確認すると、
id = 1,
name="CreateExample", が挿入される。
次にidを指定し/createにアクセスすると、、、

TestController.php
public function create()
    {
        Test::create([
            'id' => 10,
            'name' => 'CreateExample',
        ]);
    }

id = 2,
name="CreateExample", が挿入される。

10を指定しているのにもかからわず、2となる。

$guardedのおかげで指定したidではない値が自動で挿入される

save()メソッド

createメソッドと同じ挙動ですが、違いはコード量です

TestController.php
public function save()
    {
        $test = new Test();
        $test->fill([
            'name' => 'TestExample',
        ]);
        $test->save();
    }

この状態で/saveにアクセスし、DBを確認すると、
id = 1,
name="CreateExample", が挿入される。
次にidを指定し/saveにアクセスすると、、、

TestController.php
public function save()
    {
        $test = new Test();
        $test->fill([
            'name' => 'TestExample',
        ]);
        $test->save();
    }

id = 2,
name="CreateExample", が挿入される。

10を指定しているのにもかからわず、2となる。

$guardedのおかげで指定したidではない値が自動で挿入される

insert()メソッド

TestController.php
public function insert()
    {
        $test = new Test();
        $test::insert([
            'name' => 'InsertExample',
        ]);
    }

この状態で/insertにアクセスし、DBを確認すると、
id = 1,
name="CreateExample", が挿入される。
次にidを指定し/insertにアクセスすると、、、

TestController.php
public function insert()
    {
        $test = new Test();
        $test::insert([
            'id' => 10,
            'name' => 'InsertExample',
        ]);
    }

id = 10,
name="CreateExample", が挿入される。

insertメソッドではid => 10を指定すれば、10となる。
次にコードを変えずにもう一度/insertにアクセスしてみると、、、
PRIMARY KEYが重複していますというエラーが出てしまいます。

insertメソッドは$guarded$fillableの制約を受けないため、思わぬバグを生む可能性がある

追記 2024/7/19

下記コメントを頂戴し、修正。

メソッドの違いではなく
Illuminate\Database\Eloquent\Builderと
Illuminate\Database\Query\Builderの違い。
Illuminate\Database\Eloquent\Modelから始まり、ModelにないメソッドはEloquent\Builderから探す、Eloquent\BuilderにもなければQuery\Builderから探す、という処理の移行がLaravel内で勝手に行われる。
ここを理解してないとEloquentを使ってるつもりで知らないうちにQuery Builderを使うことになる。
$fillableなどはEloquentの機能なのでQuery Builderに移ったら使えない。
慣れてる人はEloquentのメソッドしか使わずQuery Builderに処理が移らないように気を付けている。
新規作成はcreate()。更新はfill()->save()。
insert() update()は使わない。

@pop-culture-studio様より

2
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?