Contents
Laravel DB 操作 Eloquent
Eloquent を見てきます。
Eloquent
Eloquent は ORM です。
モデルクラスのインスタンスを返します。
モデル取得
all
すべての結果を取得するにはall
メソッドを使います。
1 2 3 4 |
$user = User::all(); // query select * from `users` |
find
主キーで指定したモデル取得するにはfind
メソッドを使います。
1 2 3 4 |
$user = User::find(1); // query select * from `users` where `users`.`id` = 1 limit 1 |
複数のレコードを取得するにはfind
メソッドに主キーを配列で渡します。
1 2 3 4 |
$user = User::find([1, 2, 3]); // query select * from `users` where `users`.`id` in (1, 2, 3) |
first
条件にマッチした最初のモデル取得するにはfirst
メソッドを使います。
1 2 3 4 |
$user = User::where('name', 'vistylee')->first(); // query select * from `users` where `name` = 'vistylee' limit 1 |
firstWhere
条件にマッチした最初のモデル取得する短縮記法はfirstWhere
メソッドを使います。
1 2 3 4 |
$user = User::firstWhere('name', 'vistylee'); // query select * from `users` where `name` = 'vistylee' limit 1 |
firstOr
最初の結果が見つからない場合コールバックを実行するにはfirstOr
メソッドを使います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$user = User::where('name', 'like', 'viv%') ->firstOr(function () { // ... }); // カラム指定 $user = User::where('name', 'like', 'viv%') ->firstOr(['id', 'name'], function () { // ... }); // query select * from `users` where `name` like 'viv%' limit 1 select `id`, `name` from `users` where `name` like 'viv%' limit 1 |
findOrFail
モデルが見つからない時、404を返すにはfindOrFail
メソッドを使います。
1 2 3 4 5 6 7 8 |
$user = User::findOrFail(99); $user = App\User::where('id', '>', 100)->firstOrFail(); // query select * from `users` where `users`.`id` = 99 limit 1 select * from `users` where `id` > 100 limit 1 |
集計
count
カウントするにはcountメソッドを使います。
1 2 3 4 |
$count = User::where('id', '>', 10)->count(); // query select count(*) as aggregate from `users` where `id` > 10 |
max
最大値を取得するにはmax
メソッドを使います。
1 2 3 4 5 |
$max = User::where('id', '>', 10)->max('old'); // query select max(`old`) as aggregate from `users` where `id` > 10 |
min
最小値を取得するにはmin
メソッドを使います。
1 2 3 4 |
$min = User::where('id', '>', 10)->min('old'); // query select min(`old`) as aggregate from `users` where `id` > 10 |
avg
アベレージを取得するにはavg
メソッドを使います。
1 2 3 4 |
$avg = User::where('id', '>', 10)->avg('old'); // query select avg(`old`) as aggregate from `users` where `id` > 10 |
sum
合計値を取得するにはsum
メソッドを使います。
1 2 3 4 |
$sum = User::where('id', '>', 10)->sum('old'); // query select sum(`old`) as aggregate from `users` where `id` > 10 |
モデルの追加と更新
save
モデル追加をするにはsave
メソッドを使います。
1 2 3 4 5 6 7 8 |
$user = new User(); $user->name = 'vistylee'; $user->email = 'vistylee@vistylee.com'; $user->password = 'password'; $user->save(); // query insert into `users` (`name`, `email`, `password`, `updated_at`, `created_at`) values ('vistylee', 'vistylee@vistylee.com', 'password', '2020-01-01 11:22:33', '2020-01-01 11:22:33') |
モデル更新するにはsave
メソッドを使います。
1 2 3 4 5 6 7 |
$uservey = Survey::find(1); $uservey->status = 1; $uservey->save(); // query select * from `surveys` where `surveys`.`id` = 1 limit 1 update `surveys` set `status` = 1, `surveys`.`updated_at` = '2020-01-01 11:22:33' where `id` = 1 |
update
複数モデルの更新をするにはupdate
メソッドを使います。
1 2 3 4 5 |
Survey::where('id', '<', 10) ->update(['status' => 1]); // query update `surveys` set `status` = 1, `surveys`.`updated_at` = '2020-01-01 11:22:33' where `id` < 10 |
create
一行で新しいモデルを保存するにはcreate
メソッドを使います。
モデルへfillable
属性かguarded
属性どちらかの設定が必要となります。
1 2 3 4 |
$survey = Survey::create(['name' => 'survey']); // query insert into `surveys` (`name`, `updated_at`, `created_at`) values ('survey', '2020-01-01 11:22:33', '2020-01-01 11:22:33') |
firstOrCreate
モデルがなければレコード挿入してモデル生成するにはfirstOrCreate
メソッドを使います。
第2引数があれば、その属性も同時にレコード挿入します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// nameで指定したモデルが存在しなければ作成 $survey = Survey::firstOrCreate(['name' => 'survey']); // nameで指定したモデルが存在しなければname、type、statusを含め作成 $survey = Survey::firstOrCreate( ['name' => 'survey'], ['type' => 3, 'status' => 1] ); // query select * from `surveys` where (`name` = 'survey') limit 1 insert into `surveys` (`name`, `updated_at`, `created_at`) values ('survey', '2020-01-01 11:22:33', '2020-01-01 11:22:33') select * from `surveys` where (`name` = 'survey') limit 1 insert into `surveys` (`name`, `status`, `updated_at`, `created_at`) values ('survey', 1, '2020-01-01 11:22:33', '2020-01-01 11:22:33') |
firstOrNew
モデルが存在しない場合に、新しいモデルインスタンスを返すにはfirstOrNew
メソッドを使います。
データベースに保存するにはsave
メソッドが必要です。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// nameで取得するか、インスタンス化する $survey = Survey::firstOrNew(['name' => 'survey']); // nameで指定したモデルが存在しなければname、type、statusを含めインスタンス化する $survey = Survey::firstOrNew( ['name' => 'survey'], ['type' => 3, 'status' => 1] ); // query select * from `surveys` where (`name` = 'survey') limit 1 select * from `surveys` where (`name` = 'survey') limit 1 |
updateOrCreate
モデルを更新、存在しない場合は新しいモデルを作成するにはupdateOrCreate
メソッドを使います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// 既存のモデルを更新、一致するモデルがなければ作成 $survey = Survey::updateOrCreate( ['name' => 'survey'], ['type' => 3, 'status' => 1] ); $survey = Survey::updateOrCreate( ['name' => 'survey'], ['type' => 1, 'status' => 2] ); // query select * from `surveys` where (`name` = 'survey') limit 1 insert into `surveys` (`name`, `status`, `updated_at`, `created_at`) values ('survey', 1, '2020-01-01 11:22:33', '2020-01-01 11:22:33') select * from `surveys` where (`name` = 'survey') limit 1 update `surveys` set `status` = 2, `type` = 1, `surveys`.`updated_at` = '2020-08-22 08:32:15' where `id` = 1 |
判定
isDirty / isClean
属性変化の判定をするにはisDirty
メソッド、isClean
メソッドを使います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
$survey = Survey::create([ 'name' => 'survey', 'status' => 1, ]); $survey->type = 2; // 変化があったか $survey->isDirty(); // true $survey->isDirty('type'); // true $survey->isDirty('name'); // false // 変化なしか $survey->isClean(); // false $survey->isClean('type'); // false $survey->isClean('name'); // true // 更新 $survey->save(); // 更新後にチェック $survey->isDirty(); // false $survey->isClean(); // true // query insert into `surveys` (`name`, `status`, `updated_at`, `created_at`) values ('survey', 1, '2020-01-01 11:22:33', '2020-01-01 11:22:33') update `surveys` set `type` = 2, `surveys`.`updated_at` = '2020-01-01 11:22:34' where `id` = 1 |
wasChanged
最後にモデルが保存されたときから属性に変化があったかを判定するにはwasChanged
メソッドを使います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$survey = Survey::create([ 'name' => 'survey', 'type' => 2, 'status' => 1, ]); $survey->status = 2; $survey->save(); $survey->wasChanged(); // true $survey->wasChanged('status'); // true $survey->wasChanged('name'); // false // query insert into `surveys` (`name`, `type`, `status`, `updated_at`, `created_at`) values ('survey', 2, 1, '2020-01-01 11:22:33', '2020-01-01 11:22:33') update `surveys` set `status` = 2, `surveys`.`updated_at` = '2020-01-01 11:22:34' where `id` = 1 |
削除
delete
モデルを削除するにはdelete
メソッドを使います。
複数削除文はモデルイベントが発行されません。
1 2 3 4 5 6 7 8 9 |
User::find(1)->delete(); Survey::where('status', 0)->delete(); // query select * from `users` where `users`.`id` = 1 limit 1 delete from `users` where `id` = 1 delete from `surveys` where `status` = 0 |
destroy
キー指定で削除するにはdestroy
メソッドを使います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
User::destroy(1); User::destroy(1, 2, 3); User::destroy([1, 2, 3]); User::destroy(collect([1, 2, 3])); // query select * from `users` where `id` in (1) delete from `users` where `id` = 1 select * from `users` where `id` in (1, 2, 3) delete from `users` where `id` = 1 delete from `users` where `id` = 2 delete from `users` where `id` = 3 select * from `users` where `id` in (1, 2, 3) delete from `users` where `id` = 1 delete from `users` where `id` = 2 delete from `users` where `id` = 3 select * from `users` where `id` in (1, 2, 3) delete from `users` where `id` = 1 delete from `users` where `id` = 2 delete from `users` where `id` = 3 |
論理削除
テーブルにdeleted_at
カラムとモデルにSoftDeletesトレイトをセットして論理削除を有効にします。
delete
メソッドでdeleted_at
カラムに現在の時間がセットされます。
1 2 3 4 5 6 |
use Illuminate\Database\Eloquent\SoftDeletes class Survey extends Model { use SoftDeletes; } |
1 2 3 4 5 |
Survey::find(1)->delete(); // query select * from `surveys` where `surveys`.`id` = 1 and `surveys`.`deleted_at` is null limit 1 update `surveys` set `deleted_at` = '2020-01-01 11:22:34', `surveys`.`updated_at` = '2020-01-01 11:22:34' where `id` = 1 |
trashed
論理削除されているかを確認するには、trashed
メソッドを使います。
1 2 3 4 5 6 7 8 9 10 11 |
$survey = Survey::find(1); $survey = Survey::withTrashed()->find(1); if ($survey->trashed()) { // } // query select * from `surveys` where `surveys`.`id` = 1 and `surveys`.`deleted_at` is null limit 1 select * from `surveys` where `surveys`.`id` = 1 limit 1 |
withTrashed
論理削除済みのモデルも含めて取得するにはwithTrashed
メソッドを使います。
1 2 3 4 5 6 |
$survey = Survey::withTrashed() ->where('status', 1) ->get(); // query select * from `surveys` where `status` = 1 |
onlyTrashed
論理削除済みのモデルだけを取得するにはonlyTrashed
メソッドを使います。
1 2 3 4 5 6 |
$survey = Survey::onlyTrashed() ->where('status', 1) ->get(); // query select * from `surveys` where `surveys`.`deleted_at` is not null and `status` = 1 |
restore
論理削除を有効な状態に更新するにはrestore
メソッドを使います。
1 2 3 4 5 6 7 8 9 10 11 12 |
Survey::withTrashed()->find(1)->restore(); // 一括 $survey = Survey::withTrashed() ->where('status', 1) ->restore(); // query select * from `surveys` where `surveys`.`id` = 1 limit 1 update `surveys` set `deleted_at` = '', `surveys`.`updated_at` = '2020-01-01 11:22:33' where `id` = 1 update `surveys` set `deleted_at` = '', `surveys`.`updated_at` = '2020-01-01 11:22:34' where `status` = 1 |
forceDelete
完全に削除するにはforceDelete
メソッドを使います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// 1モデルを完全に削除する $survey = Survey::withTrashed()->find(1); $survey->forceDelete(); // 関係するモデルを全部完全に削除する Survey::withTrashed() ->where('status', 1) ->forceDelete(); // query select * from `surveys` where `surveys`.`id` = 1 limit 1 delete from `surveys` where `id` = 1 delete from `surveys` where `status` = 1 |
replicate
モデルを複製するにはreplicate
メソッドを使います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$survey = Survey::create([ 'name' => 'survey', 'type' => 1, 'status' => 1, ]); $repSurvey = $survey->replicate()->fill([ 'type' => 2, 'status' => 0 ]); $repSurvey->save(); // query insert into `surveys` (`name`, `type`, `status`, `updated_at`, `created_at`) values ('survey', 1, 1, '2020-01-01 11:22:34', '2020-01-01 11:22:34') insert into `surveys` (`name`, `type`, `status`, `updated_at`, `created_at`) values ('survey', 2, 0, '2020-01-01 11:22:34', '2020-01-01 11:22:34') |
クエリスコープ
グローバルスコープ
- 作成
デフォルトでは生成する artisan コマンドがないので手動で作成します。
package を追加で拡張することもできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
namespace App\Scopes; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Scope; class TypeScope implements Scope { /** * Apply the scope to a given Eloquent query builder. * * @param \Illuminate\Database\Eloquent\Builder $builder * @param \Illuminate\Database\Eloquent\Model $model * @return void */ public function apply(Builder $builder, Model $model) { $builder->where('type', '>', 1); } } |
- 適用
モデルに適用にするにはboot
メソッドを使います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// Scopeを呼び出して使う場合 use App\Scopes\TypeScope; protected static function boot() { parent::boot(); static::addGlobalScope(new TypeScope); } // クロージャを使う場合 use Illuminate\Database\Eloquent\Builder; protected static function boot() { parent::boot(); static::addGlobalScope('type', function (Builder $builder) { $builder->where('type', '>', 1); }); } |
- 実行
1 2 3 4 |
Survey::all(); // query select * from `surveys` where `type` > 1 |
- グローバルスコープの削除
グローバルスコープを除外して実行したい場合
1 2 3 4 5 6 7 8 |
// Scopeを呼び出して使っている場合 Survey::withoutGlobalScope(TypeScope::class)->get(); // クロージャを使っている場合 Survey::withoutGlobalScope('type')->get(); // query select * from `surveys` |
ローカルスコープ
- 定義
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
/** * タイプが1以上だけに限定 * * @param \Illuminate\Database\Eloquent\Builder $query * @return \Illuminate\Database\Eloquent\Builder */ public function scopeType($query) { return $query->where('type', '>=', 1); } /** * ステータスが1だけに限定 * * @param \Illuminate\Database\Eloquent\Builder $query * @return \Illuminate\Database\Eloquent\Builder */ public function scopeStatus($query) { return $query->where('status', 1); } /** * タイプ限定の値を動的にする場合 * * @param \Illuminate\Database\Eloquent\Builder $query * @return \Illuminate\Database\Eloquent\Builder */ public function scopeType($query, $type) { return $query->where('type', '>=', $type); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Survey::type()->status()->orderBy('created_at')->get(); // or 条件を使用する場合 Survey::type()->orWhere->status()->get(); // タイプの値を渡す場合 Survey::type(2)->status()->get(); // query select * from `surveys` where `type` >= 1 and `status` = 1 order by `created_at` asc select * from `surveys` where `type` >= 1 or (`status` = 1) select * from `surveys` where `type` >= 2 and `status` = 1 |
モデルの比較
is
モデルと別モデルを比較するにはis
メソッドを使います。
1 2 3 4 5 6 7 |
$surveyA = Survey::find(1); $surveyB = Survey::find(1); $surveyA->is($surveyB); // true $surveyA = Survey::find(1); $surveyB = Survey::find(2); $surveyA->is($surveyB); // false |
イベント
creating、created
レコードの挿入時にcreating
イベントが発行されます。
レコード挿入の完了時にcreated
イベントが発行されます。
updating、updated
レコードの更新時にupdating
イベントが発行されます。
レコード更新の完了時にupdated
イベントが発行されます。
saving、saved
save 時にsaving
イベントが発行されます。
save 完了時にsaved
イベントが発行されます。
deleting、deleted
delete 時にdeleting
イベントが発行されます。
delete 完了時にdeleted
イベントが発行されます。
restoring、restored
restore 時にrestoring
イベントが発行されます。
restore 完了時にrestored
イベントが発行されます。
retrieved
データベースから既存のモデルを取得時に発行されます。
dispatchesEvents
dispatchesEvents
プロパティを定義します。
事前にApp\Events\にイベントクラスを用意します。
artisan コマンドで作成できます。
1 2 3 4 5 |
php artisan make:event SurveySaved php artisan make:event SurveyCreated php artisan make:event SurveyDeleted |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
use App\Models\Survey; class SurveySaved { /** * Create a new event instance. * * @return void */ public function __construct(Survey $survey) { $this->survey = $survey; } } |
モデルでイベントクラスへマップします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
namespace App\Models; use Illuminate\Database\Eloquent\Model; use App\Events\SurveyDeleted; use App\Events\SurveySaved; use App\Events\SurveyCreated; class Survey extends Model { /** * モデルのイベントマップ * * @var array */ protected $dispatchesEvents = [ 'created' => SurveyCreated::class, 'saved' => SurveySaved::class, 'deleted' => SurveyDeleted::class, ]; } |
オブザーバ
observe
オブザーバを登録するにはobserve
メソッドを使います。
- 事前にApp\Observers\にオブザーバクラスを用意します。
artisan コマンドで作成できます。
1 |
php artisan make:observer SurveyObserver --model=Survey |
- オブザーバクラス
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
namespace App\Observers; use App\Models\Survey; class SurveyObserver { /** * Handle the survey "created" event. * * @param \App\Survey $survey * @return void */ public function created(Survey $survey) { // } /** * Handle the survey "updated" event. * * @param \App\Survey $survey * @return void */ public function updated(Survey $survey) { // } /** * Handle the survey "deleted" event. * * @param \App\Survey $survey * @return void */ public function deleted(Survey $survey) { // } /** * Handle the survey "restored" event. * * @param \App\Survey $survey * @return void */ public function restored(Survey $survey) { // } /** * Handle the survey "force deleted" event. * * @param \App\Survey $survey * @return void */ public function forceDeleted(Survey $survey) { // } } |
- オブザーバーを登録
1例としてサービスプロバイダのboot
メソッドで登録します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
namespace App\Providers; use Illuminate\Support\ServiceProvider; use App\Models\Survey; use App\Observers\SurveyObserver; class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services. * * @return void */ public function boot() { Survey::observe(SurveyObserver::class); } } |
参考リンク
Eloquent: Getting Started
Laravel 6.x Eloquent:利用の開始