Readouble

Laravel 11.x Eloquentの準備

イントロダクションIntroduction

Laravelは、データベース操作を楽しくする、オブジェクトリレーショナルマッパー(ORM)であるEloquentを用意しています。Eloquentを使用する場合、各データベーステーブルに対応する「モデル」があり、そのテーブル操作に使用します。Eloquentモデルは、データベーステーブルからレコードを取得するだけでなく、テーブルへのレコード挿入、更新、削除も可能です。Laravel includes Eloquent, an object-relational mapper (ORM) that makes it enjoyable to interact with your database. When using Eloquent, each database table has a corresponding "Model" that is used to interact with that table. In addition to retrieving records from the database table, Eloquent models allow you to insert, update, and delete records from the table as well.

lightbulb Note: 使用開始前に、必ずアプリケーションのconfig/database.php設定ファイルで、データベース接続を設定してください。データベース設定の詳細は、データベース設定のドキュメントで確認してください。[!NOTE]
Before getting started, be sure to configure a database connection in your application's config/database.php configuration file. For more information on configuring your database, check out the database configuration documentation[/docs/{{version}}/database#configuration].

Laravel BootcampLaravel Bootcamp

Laravelが初めての方は、Laravel Bootcampに気軽に飛び込んでみてください。Laravel Bootcampは、Eloquentを使って初めてのLaravelアプリケーションを構築する方法を説明します。LaravelとEloquentが提供するすべてを知るには最適な方法です。If you're new to Laravel, feel free to jump into the Laravel Bootcamp[https://bootcamp.laravel.com]. The Laravel Bootcamp will walk you through building your first Laravel application using Eloquent. It's a great way to get a tour of everything that Laravel and Eloquent have to offer.

モデルクラスの生成Generating Model Classes

使用を開始するには、Eloquentモデルを作成しましょう。モデルは通常app\Modelsディレクトリにあり、Illuminate\Database\Eloquent\Modelクラスを拡張します。make:model Artisanコマンドを使用して、新しいモデルを生成します。To get started, let's create an Eloquent model. Models typically live in the app\Models directory and extend the Illuminate\Database\Eloquent\Model class. You may use the make:model Artisan command[/docs/{{version}}/artisan] to generate a new model:

php artisan make:model Flight

モデルの生成時にデータベースマイグレーションも生成する場合は、--migrationまたは-mオプションを使用します。If you would like to generate a database migration[/docs/{{version}}/migrations] when you generate the model, you may use the --migration or -m option:

php artisan make:model Flight --migration

モデルを生成するとき、ファクトリ、シーダ、コントローラ、ポリシー、フォームリクエストなど、他のさまざまなタイプのクラスを同時に生成できます。さらにこれらのオプションを組み合わせて、一度に複数のクラスを作成できます。You may generate various other types of classes when generating a model, such as factories, seeders, policies, controllers, and form requests. In addition, these options may be combined to create multiple classes at once:

# モデルとFlightFactoryクラスを生成
php artisan make:model Flight --factory
php artisan make:model Flight -f

# モデルとFlightSeederクラスを生成
php artisan make:model Flight --seed
php artisan make:model Flight -s

# モデルとFlightControllerクラスを生成
php artisan make:model Flight --controller
php artisan make:model Flight -c

# モデルとFlightControllerリソースクラス、フォームリクエストクラスを生成
php artisan make:model Flight --controller --resource --requests
php artisan make:model Flight -crR

# モデルとFlightPolicyクラスを生成
php artisan make:model Flight --policy

# モデルとマイグレーション、ファクトリ、シーダ、およびコントローラを生成
php artisan make:model Flight -mfsc

# モデルとマイグレーション、ファクトリ、シーダ、ポリシー、コントローラ、フォームリクエストを生成する短縮形
php artisan make:model Flight --all
php artisan make:model Flight -a

# ピボットモデルを生成
php artisan make:model Member --pivot
php artisan make:model Member -p

モデルの調査Inspecting Models

モデルのコードに目を通すだけでは、そのモデルで利用可能な全ての属性とリレーションを判断するのが難しい場合があります。そのような場合は、model:show Artisanコマンドを使用してください。モデルの全ての属性とリレーションを簡単に確認できます。Sometimes it can be difficult to determine all of a model's available attributes and relationships just by skimming its code. Instead, try the model:show Artisan command, which provides a convenient overview of all the model's attributes and relations:

php artisan model:show Flight

Eloquentモデルの規約Eloquent Model Conventions

make:modelコマンドで生成されたモデルは、app/Modelsディレクトリに配置します。基本的なモデルクラスを調べて、Eloquentの主要な規約をいくつか説明しましょう。Models generated by the make:model command will be placed in the app/Models directory. Let's examine a basic model class and discuss some of Eloquent's key conventions:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    // ...
}

テーブル名Table Names

上記の例をちょっと見て、どのデータベーステーブルがFlightモデルに対応するかをEloquentに知らせていないことにお気づきかもしれません。別の名前を明示的に指定しない限り、クラスの複数形の「スネークケース」をテーブル名として使用します。したがって、この場合、EloquentはFlightモデルがflightsテーブルにレコードを格納し、AirTrafficControllerモデルはair_traffic_controllersテーブルにレコードを格納すると想定できます。After glancing at the example above, you may have noticed that we did not tell Eloquent which database table corresponds to our Flight model. By convention, the "snake case", plural name of the class will be used as the table name unless another name is explicitly specified. So, in this case, Eloquent will assume the Flight model stores records in the flights table, while an AirTrafficController model would store records in an air_traffic_controllers table.

モデルの対応するデータベーステーブルがこの規約に適合しない場合は、モデルにtableプロパティを定義してモデルのテーブル名を自分で指定できます。If your model's corresponding database table does not fit this convention, you may manually specify the model's table name by defining a table property on the model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * モデルに関連付けるテーブル
     *
     * @var string
     */
    protected $table = 'my_flights';
}

主キーPrimary Keys

Eloquentは、各モデルの対応するデータベーステーブルにidという名前の主キーカラムがあることも想定しています。必要に応じて、モデルのprotected $primaryKeyプロパティを定義して、主キーとして機能する別のカラムを指定できます。Eloquent will also assume that each model's corresponding database table has a primary key column named id. If necessary, you may define a protected $primaryKey property on your model to specify a different column that serves as your model's primary key:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * テーブルに関連付ける主キー
     *
     * @var string
     */
    protected $primaryKey = 'flight_id';
}

さらに、Eloquentは、主キーが増分整数値であることも想定しています。これは、Eloquentが主キーを自動的に整数にキャストすることを意味します。非インクリメントまたは非数値の主キーを使用する場合は、モデルにpublicの$incrementingプロパティを定義し、falseをセットする必要があります。In addition, Eloquent assumes that the primary key is an incrementing integer value, which means that Eloquent will automatically cast the primary key to an integer. If you wish to use a non-incrementing or a non-numeric primary key you must define a public $incrementing property on your model that is set to false:

<?php

class Flight extends Model
{
    /**
     * モデルのIDを自動増分するか
     *
     * @var bool
     */
    public $incrementing = false;
}

モデルの主キーが整数でない場合は、モデルにprotectedな$keyTypeプロパティを定義する必要があります。このプロパティの値はstringにする必要があります。If your model's primary key is not an integer, you should define a protected $keyType property on your model. This property should have a value of string:

<?php

class Flight extends Model
{
    /**
     * 主キーIDのデータ型
     *
     * @var string
     */
    protected $keyType = 'string';
}

「コンポジット」主キー"Composite" Primary Keys

Eloquentは、それぞれのモデルがその主キーとして役立つことができる、少なくとも1つの一意に識別される「ID」を持つ必要があります。Eloquentモデルは「コンポジット」主キーをサポートしていません。しかし、テーブルの一意に識別される主キーに加えて、データベーステーブルに追加のマルチカラム、ユニークなインデックスを追加することができます。Eloquent requires each model to have at least one uniquely identifying "ID" that can serve as its primary key. "Composite" primary keys are not supported by Eloquent models. However, you are free to add additional multi-column, unique indexes to your database tables in addition to the table's uniquely identifying primary key.

UUIDとULIDキーUUID and ULID Keys

Eloquentモデルの主キーへ、自動増分整数を使用する代わりに、UUIDが使用できます。UUIDは36文字の英数字で構成される一意な識別子です。Instead of using auto-incrementing integers as your Eloquent model's primary keys, you may choose to use UUIDs instead. UUIDs are universally unique alpha-numeric identifiers that are 36 characters long.

モデルで自動インクリメントの整数キーの代わりにUUIDキーを使用したい場合は、そのモデルでIlluminate\Database\Eloquent\Concerns\HasUuidsトレイトを使用します。もちろん、モデルへUUIDの主キーカラムを確実に持たせてください。If you would like a model to use a UUID key instead of an auto-incrementing integer key, you may use the Illuminate\Database\Eloquent\Concerns\HasUuids trait on the model. Of course, you should ensure that the model has a UUID equivalent primary key column[/docs/{{version}}/migrations#column-method-uuid]:

use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
    use HasUuids;

    // ...
}

$article = Article::create(['title' => 'Traveling to Europe']);

$article->id; // "8f8e8478-9035-4d23-b9a7-62f4d2612ce5"

HasUuidsトレイトはデフォルトで、モデルに対し順序付き(ordered)UUIDを生成します。これらのUUIDは辞書式にソートすることができるため、インデックス付きデータベースの保存が効率的です。By default, The HasUuids trait will generate "ordered" UUIDs[/docs/{{version}}/strings#method-str-ordered-uuid] for your models. These UUIDs are more efficient for indexed database storage because they can be sorted lexicographically.

モデルへnewUniqueIdメソッドを定義すれば、指定モデルのUUID生成処理をオーバーライドできます。さらに、モデルにuniqueIdsメソッドを定義すれば、UUIDをどのカラムで受け取るのかを指定できます。You can override the UUID generation process for a given model by defining a newUniqueId method on the model. In addition, you may specify which columns should receive UUIDs by defining a uniqueIds method on the model:

use Ramsey\Uuid\Uuid;

/**
 * モデルの新しいUUIDの生成
 */
public function newUniqueId(): string
{
    return (string) Uuid::uuid4();
}

/**
 * 一意の識別子を受け取るカラムの取得
 *
 * @return array<int, string>
 */
public function uniqueIds(): array
{
    return ['id', 'discount_code'];
}

ご希望であれば、UUIDの代わりに"ULID"を使用することもできます。ULIDはUUIDに似ていますが、長さは26文字です。順序付きUUIDのように、ULIDは効率的なデータベースインデックス作成のため、辞書的にソート可能です。ULIDを使用するには、モデルで Illuminate\Database\Eloquent\Concerns\HasUlidsトレイトを使用してください。また、モデルにULID相当の主キーカラム確実に用意する必要があります。If you wish, you may choose to utilize "ULIDs" instead of UUIDs. ULIDs are similar to UUIDs; however, they are only 26 characters in length. Like ordered UUIDs, ULIDs are lexicographically sortable for efficient database indexing. To utilize ULIDs, you should use the Illuminate\Database\Eloquent\Concerns\HasUlids trait on your model. You should also ensure that the model has a ULID equivalent primary key column[/docs/{{version}}/migrations#column-method-ulid]:

use Illuminate\Database\Eloquent\Concerns\HasUlids;
use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
    use HasUlids;

    // ...
}

$article = Article::create(['title' => 'Traveling to Asia']);

$article->id; // "01gd4d3tgrrfqeda94gdbtdk5c"

主キータイムスタンプTimestamps

デフォルトでEloquentは、モデルと対応するデータベーステーブルに、created_atカラムとupdated_atカラムが存在していると想定します。Eloquentはモデルが作成または更新されるときに、これらの列の値を自動的にセットします。これらのカラムがEloquentによって自動的に管理されないようにする場合は、モデルに$timestampsプロパティを定義し、false値をセットします。By default, Eloquent expects created_at and updated_at columns to exist on your model's corresponding database table. Eloquent will automatically set these column's values when models are created or updated. If you do not want these columns to be automatically managed by Eloquent, you should define a $timestamps property on your model with a value of false:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * モデルにタイムスタンプを付けるか
     *
     * @var bool
     */
    public $timestamps = false;
}

モデルのタイムスタンプのフォーマットをカスタマイズする必要がある場合は、モデルに$dateFormatプロパティを設定します。このプロパティはモデルが配列やJSONへシリアル化されるときに、日付属性がデータベースに格納される方法とその形式を決定します。If you need to customize the format of your model's timestamps, set the $dateFormat property on your model. This property determines how date attributes are stored in the database as well as their format when the model is serialized to an array or JSON:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * モデルの日付カラムの保存用フォーマット
     *
     * @var string
     */
    protected $dateFormat = 'U';
}

タイムスタンプの保存に使用するカラム名をカスタマイズする必要がある場合は、モデルにCREATED_ATおよびUPDATED_AT定数を定義してください。If you need to customize the names of the columns used to store the timestamps, you may define CREATED_AT and UPDATED_AT constants on your model:

<?php

class Flight extends Model
{
    const CREATED_AT = 'creation_date';
    const UPDATED_AT = 'updated_date';
}

モデルのupdated_atタイムスタンプを変更せずに、モデル操作を行いたい場合は、withoutTimestampsメソッドへ指定するクロージャ内で、そのモデルを操作できます。If you would like to perform model operations without the model having its updated_at timestamp modified, you may operate on the model within a closure given to the withoutTimestamps method:

Model::withoutTimestamps(fn () => $post->increment('reads'));

データベース接続Database Connections

デフォルトですべてのEloquentモデルは、アプリケーション用に設定したデフォルトのデータベース接続を使用します。特定のモデルと対話するときに別の接続を使用する必要がある場合は、モデルに$connectionプロパティを定義する必要があります。By default, all Eloquent models will use the default database connection that is configured for your application. If you would like to specify a different connection that should be used when interacting with a particular model, you should define a $connection property on the model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * このモデルが使用するデータベース接続
     *
     * @var string
     */
    protected $connection = 'mysql';
}

デフォルト属性値Default Attribute Values

デフォルトでは、新しくインスタンス化するモデルインスタンスに属性値は含まれません。モデルの属性の一部にデフォルト値を定義したい場合は、モデルに$attributesプロパティを定義できます。$attributes配列に格納する属性値は、データベースから読み込んだままのような、素の「保存可能」形式であるべきです。By default, a newly instantiated model instance will not contain any attribute values. If you would like to define the default values for some of your model's attributes, you may define an $attributes property on your model. Attribute values placed in the $attributes array should be in their raw, "storable" format as if they were just read from the database:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * モデルの属性のデフォルト値
     *
     * @var array
     */
    protected $attributes = [
        'options' => '[]',
        'delayed' => false,
    ];
}

Eloquent厳格さの設定Configuring Eloquent Strictness

Laravelは、さまざまな状況におけるEloquent動作や、「厳密さ」を設定するためメソッドを用意しています。Laravel offers several methods that allow you to configure Eloquent's behavior and "strictness" in a variety of situations.

まず、preventLazyLoadingメソッドは、オプションで論理値の引数を取り、遅延ロードを防ぐかを指定します。たとえば、非本番環境のみ遅延ロードを無効にし、本番環境にリレーションを遅延ロードするコードが誤って紛れ込んだ場合でも、正常に機能し続けるようにしたい状況はあると思います。通常、このメソッドはアプリケーションのAppServiceProviderbootメソッドで呼び出す必要があります。First, the preventLazyLoading method accepts an optional boolean argument that indicates if lazy loading should be prevented. For example, you may wish to only disable lazy loading in non-production environments so that your production environment will continue to function normally even if a lazy loaded relationship is accidentally present in production code. Typically, this method should be invoked in the boot method of your application's AppServiceProvider:

use Illuminate\Database\Eloquent\Model;

/**
 * 全アプリケーションサービスの初期起動処理
 */
public function boot(): void
{
    Model::preventLazyLoading(! $this->app->isProduction());
}

また、preventSilentlyDiscardingAttributesメソッドを呼び出せば、複数代入非許可な属性へ複数代入しようとしたときに例外を投げるようにLaravelに指示することもできます。これは、ローカル開発時に、モデルのfillable配列へ追加されていない属性をセットしようとしたときに、予期せぬエラーが発生するのを防ぐのに役立ちます。Also, you may instruct Laravel to throw an exception when attempting to fill an unfillable attribute by invoking the preventSilentlyDiscardingAttributes method. This can help prevent unexpected errors during local development when attempting to set an attribute that has not been added to the model's fillable array:

Model::preventSilentlyDiscardingAttributes(! $this->app->isProduction());

モデルの取得Retrieving Models

モデルとそれと関連するデータベーステーブルを作成したら、データベースからデータを取得する準備が整いました。各Eloquentモデルは、モデルに関連付けたデータベーステーブルを流暢にクエリできる強力なクエリビルダと考えることができます。モデルのallメソッドは、モデルに関連付けたデータベーステーブルからすべてのレコードを取得します。Once you have created a model and its associated database table[/docs/{{version}}/migrations#generating-migrations], you are ready to start retrieving data from your database. You can think of each Eloquent model as a powerful query builder[/docs/{{version}}/queries] allowing you to fluently query the database table associated with the model. The model's all method will retrieve all of the records from the model's associated database table:

use App\Models\Flight;

foreach (Flight::all() as $flight) {
    echo $flight->name;
}

クエリの作成Building Queries

Eloquentのallメソッドは、モデルのテーブルにあるすべての結果を返します。しかし、各Eloquentモデルはクエリビルダとして機能するため、クエリに制約を追加してからgetメソッドを呼び出し、結果を取得することもできます。The Eloquent all method will return all of the results in the model's table. However, since each Eloquent model serves as a query builder[/docs/{{version}}/queries], you may add additional constraints to queries and then invoke the get method to retrieve the results:

$flights = Flight::where('active', 1)
               ->orderBy('name')
               ->take(10)
               ->get();

lightbulb Note: Eloquentモデルはクエリビルダであるため、Laravelのクエリビルダが提供するすべてのメソッドを確認する必要があります。Eloquentでクエリを作成するときは、それらすべてのメソッドを使用できます。[!NOTE]
Since Eloquent models are query builders, you should review all of the methods provided by Laravel's query builder[/docs/{{version}}/queries]. You may use any of these methods when writing your Eloquent queries.

モデルのリフレッシュRefreshing Models

データベースから取得したEloquentモデルのインスタンスがすでにある場合は、freshメソッドとrefreshメソッドを使用してモデルを「更新」できます。freshメソッドは、データベースからモデルを再取得します。既存のモデルインスタンスは影響を受けません。If you already have an instance of an Eloquent model that was retrieved from the database, you can "refresh" the model using the fresh and refresh methods. The fresh method will re-retrieve the model from the database. The existing model instance will not be affected:

$flight = Flight::where('number', 'FR 900')->first();

$freshFlight = $flight->fresh();

refreshメソッドは、データベースからの新しいデータを使用して既存のモデルを再ハイドレートします。さらに、ロードしたすべてのリレーションも更新されます。The refresh method will re-hydrate the existing model using fresh data from the database. In addition, all of its loaded relationships will be refreshed as well:

$flight = Flight::where('number', 'FR 900')->first();

$flight->number = 'FR 456';

$flight->refresh();

$flight->number; // "FR 900"

コレクションCollections

これまで見てきたように、allgetのようなEloquentメソッドは、データベースから複数のレコードを取得します。ただし、これらのメソッドはプレーンなPHP配列を返しません。代わりに、Illuminate\Database\Eloquent\Collectionのインスタンスが返されます。As we have seen, Eloquent methods like all and get retrieve multiple records from the database. However, these methods don't return a plain PHP array. Instead, an instance of Illuminate\Database\Eloquent\Collection is returned.

Eloquent CollectionクラスはLaravelの基本Illuminate\Support\Collectionクラスを拡張し、データコレクションを操作するためにさまざまな便利なメソッドを提供しています。たとえば、rejectメソッドを使用して、呼び出されたクロージャの結果に基づいてコレクションからモデルを削除できます。The Eloquent Collection class extends Laravel's base Illuminate\Support\Collection class, which provides a variety of helpful methods[/docs/{{version}}/collections#available-methods] for interacting with data collections. For example, the reject method may be used to remove models from a collection based on the results of an invoked closure:

$flights = Flight::where('destination', 'Paris')->get();

$flights = $flights->reject(function (Flight $flight) {
    return $flight->cancelled;
});

Laravelの基本コレクションクラスによって提供されるメソッドに加えて、Eloquentコレクションクラスは、Eloquentコレクション操作に特化したいくつかの追加メソッドも提供しています。In addition to the methods provided by Laravel's base collection class, the Eloquent collection class provides a few extra methods[/docs/{{version}}/eloquent-collections#available-methods] that are specifically intended for interacting with collections of Eloquent models.

LaravelのコレクションはすべてPHPのiterableなインターフェイスを実装しているため、コレクションを配列のようにループ処理できます。Since all of Laravel's collections implement PHP's iterable interfaces, you may loop over collections as if they were an array:

foreach ($flights as $flight) {
    echo $flight->name;
}

結果の分割Chunking Results

allまたはgetメソッドを使用して数万のEloquentレコードを読み込もうとすると、アプリケーションのメモリを不足させる可能性があります。これらのメソッドを使用する代わりに、chunkメソッドを使用して、多数のモデルをより効率的に処理してください。Your application may run out of memory if you attempt to load tens of thousands of Eloquent records via the all or get methods. Instead of using these methods, the chunk method may be used to process large numbers of models more efficiently.

chunkメソッドは、Eloquentモデルのサブセットを取得し、それらをクロージャに渡して処理します。Eloquentモデルの現在のチャンクのみ一度に取得されるため、chunkメソッドを使用すると大量のモデルを操作するときに、メモリ使用量が大幅に削減できます。The chunk method will retrieve a subset of Eloquent models, passing them to a closure for processing. Since only the current chunk of Eloquent models is retrieved at a time, the chunk method will provide significantly reduced memory usage when working with a large number of models:

use App\Models\Flight;
use Illuminate\Database\Eloquent\Collection;

Flight::chunk(200, function (Collection $flights) {
    foreach ($flights as $flight) {
        // ...
    }
});

chunkメソッドに渡す最初の引数は、「チャンク」ごとに受信するレコード数です。2番目の引数として渡すクロージャは、データベースから取得したチャンクごとに呼び出されます。レコードのチャンクを取得しクロージャへ渡すために、毎回データベースクエリを実行します。The first argument passed to the chunk method is the number of records you wish to receive per "chunk". The closure passed as the second argument will be invoked for each chunk that is retrieved from the database. A database query will be executed to retrieve each chunk of records passed to the closure.

結果を反復処理するときに、更新するカラムに基づいてchunkメソッドの結果をフィルタリングする場合は、chunkByIdメソッドを使用する必要があります。こうしたシナリオでchunkメソッドを使用すると、一貫性が無く予期しない結果を生じる可能性があります。内部的にchunkByIdメソッドは常に、前のチャンクの最後のモデルよりも大きいidカラムを持つモデルを取得します。If you are filtering the results of the chunk method based on a column that you will also be updating while iterating over the results, you should use the chunkById method. Using the chunk method in these scenarios could lead to unexpected and inconsistent results. Internally, the chunkById method will always retrieve models with an id column greater than the last model in the previous chunk:

Flight::where('departed', true)
    ->chunkById(200, function (Collection $flights) {
        $flights->each->update(['departed' => false]);
    }, column: 'id');

chunkByIdメソッドとlazyByIdメソッドは、実行するクエリに独自の"Where"条件を追加するため、通常はクロージャの中へ独自の条件を論理的にグループ化する必要があります。Since the chunkById and lazyById methods add their own "where" conditions to the query being executed, you should typically logically group[/docs/{{version}}/queries#logical-grouping] your own conditions within a closure:

Flight::where(function ($query) {
    $query->where('delayed', true)->orWhere('cancelled', true);
})->chunkById(200, function (Collection $flights) {
    $flights->each->update([
        'departed' => false,
        'cancelled' => true
    ]);
}, column: 'id');

レイジーコレクションを使用する分割Chunking Using Lazy Collections

lazyメソッドは、裏でチャンク単位でクエリを実行するという意味で、chunkメソッドと同様に動作します。しかし、lazyメソッドは、各チャンクをそのままコールバックへ渡すのではなく、フラット化したEloquentモデルのLazyCollectionを返すので、結果を単一のストリームとして操作できます。The lazy method works similarly to the chunk method[#chunking-results] in the sense that, behind the scenes, it executes the query in chunks. However, instead of passing each chunk directly into a callback as is, the lazy method returns a flattened LazyCollection[/docs/{{version}}/collections#lazy-collections] of Eloquent models, which lets you interact with the results as a single stream:

use App\Models\Flight;

foreach (Flight::lazy() as $flight) {
    // ...
}

もし、lazyメソッドの結果を、結果の反復処理中に更新されるカラムに基づいてフィルタリングするのであれば、lazyByIdメソッドを使うべきです。内部的には、lazyByIdメソッドは、idカラムが前のチャンクの最後のモデルよりも大きいモデルを常に取得します。If you are filtering the results of the lazy method based on a column that you will also be updating while iterating over the results, you should use the lazyById method. Internally, the lazyById method will always retrieve models with an id column greater than the last model in the previous chunk:

Flight::where('departed', true)
    ->lazyById(200, column: 'id')
    ->each->update(['departed' => false]);

lazyByIdDescメソッドを使って、idの降順に基づいて結果をフィルタリングできます。You may filter the results based on the descending order of the id using the lazyByIdDesc method.

カーソルCursors

lazyメソッドと同様に、cursorメソッドを使用すると、何万ものEloquentモデルのレコードを反復処理する際に、アプリケーションのメモリ消費量を大幅に削減できます。Similar to the lazy method, the cursor method may be used to significantly reduce your application's memory consumption when iterating through tens of thousands of Eloquent model records.

cursorメソッドは単一のデータベースクエリのみを実行します。ただし、個々のEloquentモデルは、実際の繰り返し処理までハイドレートされません。したがって、カーソルを反復処理している間、常に1つのEloquentモデルのみがメモリに保持されます。The cursor method will only execute a single database query; however, the individual Eloquent models will not be hydrated until they are actually iterated over. Therefore, only one Eloquent model is kept in memory at any given time while iterating over the cursor.

warning Warning! cursorメソッドは一度に1つのEloquentモデルしかメモリに保持しないため、リレーションをEagerロードできません。リレーションシップをEagerロードする必要がある場合は、代わりに lazyメソッド の使用を検討してください。[!WARNING]
Since the cursor method only ever holds a single Eloquent model in memory at a time, it cannot eager load relationships. If you need to eager load relationships, consider using the lazy method[#chunking-using-lazy-collections] instead.

内部的には、cursorメソッドはPHPのジェネレータを使ってこの機能を実装しています。Internally, the cursor method uses PHP generators[https://www.php.net/manual/en/language.generators.overview.php] to implement this functionality:

use App\Models\Flight;

foreach (Flight::where('destination', 'Zurich')->cursor() as $flight) {
    // ...
}

cursorIlluminate\Support\LazyCollectionインスタンスを返します。レイジーコレクションを使用すると、一度に1つのモデルのみをメモリにロードしながら、一般的なLaravelコレクションで使用できる多くのコレクションメソッドを使用できます。The cursor returns an Illuminate\Support\LazyCollection instance. Lazy collections[/docs/{{version}}/collections#lazy-collections] allow you to use many of the collection methods available on typical Laravel collections while only loading a single model into memory at a time:

use App\Models\User;

$users = User::cursor()->filter(function (User $user) {
    return $user->id > 500;
});

foreach ($users as $user) {
    echo $user->id;
}

cursorメソッドは、通常のクエリよりもはるかに少ないメモリしか使用しませんが(一度に1つのEloquentモデルをメモリ内に保持するだけです)、それでも最終的にはメモリが不足するでしょう。これは、PHPのPDOドライバが、素のクエリ結果をすべてバッファに内部的にキャッシュしているためです。非常に多くのEloquentレコードを扱う場合には、代わりにlazyメソッドの使用を検討してください。Although the cursor method uses far less memory than a regular query (by only holding a single Eloquent model in memory at a time), it will still eventually run out of memory. This is due to PHP's PDO driver internally caching all raw query results in its buffer[https://www.php.net/manual/en/mysqlinfo.concepts.buffering.php]. If you're dealing with a very large number of Eloquent records, consider using the lazy method[#chunking-using-lazy-collections] instead.

上級サブクエリAdvanced Subqueries

サブクエリのSELECTSubquery Selects

Eloquentは、高度なサブクエリサポートも提供します。これにより、単一のクエリで関連するテーブルから情報を取得できます。たとえば、フライトの「目的地」のテーブルと目的地への「フライト」のテーブルがあるとします。flightsテーブルには、フライトが目的地に到着した時刻を示すarrived_at列が含まれています。Eloquent also offers advanced subquery support, which allows you to pull information from related tables in a single query. For example, let's imagine that we have a table of flight destinations and a table of flights to destinations. The flights table contains an arrived_at column which indicates when the flight arrived at the destination.

クエリビルダのselectメソッドとaddSelectメソッドで使用できるサブクエリ機能を使用すると、1つのクエリを使用して、すべてのdestinationsとその目的地に最近到着したフライトの名前を選択できます。Using the subquery functionality available to the query builder's select and addSelect methods, we can select all of the destinations and the name of the flight that most recently arrived at that destination using a single query:

use App\Models\Destination;
use App\Models\Flight;

return Destination::addSelect(['last_flight' => Flight::select('name')
    ->whereColumn('destination_id', 'destinations.id')
    ->orderByDesc('arrived_at')
    ->limit(1)
])->get();

サブクエリの順序Subquery Ordering

さらに、クエリビルダのorderBy関数はサブクエリをサポートします。フライトの例を引き続き使用すると、この機能を使用して、最後のフライトが目的地へ到着した日時に基づいて、すべての目的地を並べ替えることができます。繰り返しますが、これは単一のデータベースクエリの実行中に実行できます。In addition, the query builder's orderBy function supports subqueries. Continuing to use our flight example, we may use this functionality to sort all destinations based on when the last flight arrived at that destination. Again, this may be done while executing a single database query:

return Destination::orderByDesc(
    Flight::select('arrived_at')
        ->whereColumn('destination_id', 'destinations.id')
        ->orderByDesc('arrived_at')
        ->limit(1)
)->get();

単一モデル/集計の取得Retrieving Single Models / Aggregates

特定のクエリに一致するすべてのレコードを取得することに加えて、findfirst、またはfirstWhereメソッドを使用して単一のレコードを取得することもできます。モデルのコレクションを返す代わりに、これらのメソッドは単一のモデルインスタンスを返します。In addition to retrieving all of the records matching a given query, you may also retrieve single records using the find, first, or firstWhere methods. Instead of returning a collection of models, these methods return a single model instance:

use App\Models\Flight;

// 主キーでモデルを取得
$flight = Flight::find(1);

// クエリの制約に一致する最初のモデルを取得
$flight = Flight::where('active', 1)->first();

// クエリの制約に一致する最初のモデルを取得する別の記法
$flight = Flight::firstWhere('active', 1);

結果が見つからない場合は、別のアクションを実行したいこともあります。findOrfirstOrメソッドは単一のモデルインスタンスを返しますが、結果が見つからなかった場合は指定クロージャを実行します。クロージャの返却値は、メソッドの結果とみなします。Sometimes you may wish to perform some other action if no results are found. The findOr and firstOr methods will return a single model instance or, if no results are found, execute the given closure. The value returned by the closure will be considered the result of the method:

$flight = Flight::findOr(1, function () {
    // ...
});

$flight = Flight::where('legs', '>', 3)->firstOr(function () {
    // ...
});

Not Found例外Not Found Exceptions

モデルが見つからない場合は、例外を投げたい場合があります。これは、ルートやコントローラでとくに役立ちます。findOrFailメソッドとfirstOrFailメソッドは、クエリの最初の結果を取得します。ただし、結果が見つからない場合は、Illuminate\Database\Eloquent\ModelNotFoundExceptionを投げます。Sometimes you may wish to throw an exception if a model is not found. This is particularly useful in routes or controllers. The findOrFail and firstOrFail methods will retrieve the first result of the query; however, if no result is found, an Illuminate\Database\Eloquent\ModelNotFoundException will be thrown:

$flight = Flight::findOrFail(1);

$flight = Flight::where('legs', '>', 3)->firstOrFail();

ModelNotFoundExceptionをキャッチしない場合は、404 HTTPレスポンスをクライアントへ自動的に返送します。If the ModelNotFoundException is not caught, a 404 HTTP response is automatically sent back to the client:

use App\Models\Flight;

Route::get('/api/flights/{id}', function (string $id) {
    return Flight::findOrFail($id);
});

モデルの取得/生成Retrieving or Creating Models

firstOrCreateメソッドは、指定したカラムと値のペアを使用してデータベースレコードを見つけようとします。モデルがデータベースで見つからない場合は、最初の配列引数をオプションの2番目の配列引数とマージした結果の属性を含むレコードが挿入されます。The firstOrCreate method will attempt to locate a database record using the given column / value pairs. If the model cannot be found in the database, a record will be inserted with the attributes resulting from merging the first array argument with the optional second array argument:

firstOrNewメソッドはfirstOrCreateのように、指定された属性に一致するデータベース内のレコードを見つけようとします。ただし、モデルが見つからない場合は、新しいモデルインスタンスが返されます。firstOrNewによって返されるモデルは、まだデータベースに永続化されていないことに注意してください。永続化するには、手作業でsaveメソッドを呼び出す必要があります。The firstOrNew method, like firstOrCreate, will attempt to locate a record in the database matching the given attributes. However, if a model is not found, a new model instance will be returned. Note that the model returned by firstOrNew has not yet been persisted to the database. You will need to manually call the save method to persist it:

use App\Models\Flight;

// 名前でフライトを取得するか、存在しない場合は作成
$flight = Flight::firstOrCreate([
    'name' => 'London to Paris'
]);

// 名前でフライトを取得するか、name、delayed、arrival_time属性を使用してフライトを作成
$flight = Flight::firstOrCreate(
    ['name' => 'London to Paris'],
    ['delayed' => 1, 'arrival_time' => '11:30']
);

// 名前でフライトを取得するか、新しいFlightインスタンスをインスタンス化
$flight = Flight::firstOrNew([
    'name' => 'London to Paris'
]);

// 名前でフライトを取得するか、name、delayed、arrival_time属性を使用してインスタンス化
$flight = Flight::firstOrNew(
    ['name' => 'Tokyo to Sydney'],
    ['delayed' => 1, 'arrival_time' => '11:30']
);

集計の取得Retrieving Aggregates

Eloquentモデルを操作するときは、Laravel クエリビルダが提供するcountsummax、およびその他の集計メソッドを使用することもできます。ご想像のとおり、これらのメソッドは、Eloquentモデルインスタンスの代わりにスカラー値を返します。When interacting with Eloquent models, you may also use the count, sum, max, and other aggregate methods[/docs/{{version}}/queries#aggregates] provided by the Laravel query builder[/docs/{{version}}/queries]. As you might expect, these methods return a scalar value instead of an Eloquent model instance:

$count = Flight::where('active', 1)->count();

$max = Flight::where('active', 1)->max('price');

モデルの挿入と更新Inserting and Updating Models

挿入Inserts

もちろん、Eloquentを使用する状況は、データベースからモデルを取得する必要がある場合だけに限りません。新しいレコードを挿入する必要もあるでしょう。うれしいことに、Eloquentはこれをシンプルにします。データベースへ新しいレコードを挿入するには、新しいモデルインスタンスをインスタンス化し、モデルに属性をセットする必要があります。次に、モデルインスタンスでsaveメソッドを呼び出します。Of course, when using Eloquent, we don't only need to retrieve models from the database. We also need to insert new records. Thankfully, Eloquent makes it simple. To insert a new record into the database, you should instantiate a new model instance and set attributes on the model. Then, call the save method on the model instance:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\Flight;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class FlightController extends Controller
{
    /**
     * 新しいフライトをデータベースに保存
     */
    public function store(Request $request): RedirectResponse
    {
        // リクエストのバリデーション処理…

        $flight = new Flight;

        $flight->name = $request->name;

        $flight->save();

        return redirect('/flights');
    }
}

この例では、受信HTTPリクエストのnameフィールドをApp\Models\Flightモデルインスタンスのname属性に割り当てます。saveメソッドを呼び出すと、レコードがデータベースに挿入されます。モデルのcreated_atおよびupdated_atタイムスタンプは、saveメソッドが呼び出されたときに自動的に設定されるため、手作業で設定する必要はありません。In this example, we assign the name field from the incoming HTTP request to the name attribute of the App\Models\Flight model instance. When we call the save method, a record will be inserted into the database. The model's created_at and updated_at timestamps will automatically be set when the save method is called, so there is no need to set them manually.

もしくは、createメソッドを使用して、単一のPHPステートメントにより、新しいモデルを「保存」することもできます。createメソッドは、その挿入したモデルインスタンスを返します。Alternatively, you may use the create method to "save" a new model using a single PHP statement. The inserted model instance will be returned to you by the create method:

use App\Models\Flight;

$flight = Flight::create([
    'name' => 'London to Paris',
]);

ただし、createメソッドを使用する前に、モデルクラスでfillableまたはguardedプロパティを指定する必要があります。すべてのEloquentモデルはデフォルトで複数代入の脆弱性から保護されているため、こうしたプロパティが必須なのです。複数代入の詳細については、複数代入のドキュメントを参照してください。However, before using the create method, you will need to specify either a fillable or guarded property on your model class. These properties are required because all Eloquent models are protected against mass assignment vulnerabilities by default. To learn more about mass assignment, please consult the mass assignment documentation[#mass-assignment].

更新Updates

saveメソッドを使用して、データベースにすでに存在するモデルを更新することもできます。モデルを更新するには、モデルを取得して、更新する属性をセットする必要があります。次に、モデルのsaveメソッドを呼び出します。この場合も、updated_atタイムスタンプを自動的に更新するため、手作業で値を設定する必要はありません。The save method may also be used to update models that already exist in the database. To update a model, you should retrieve it and set any attributes you wish to update. Then, you should call the model's save method. Again, the updated_at timestamp will automatically be updated, so there is no need to manually set its value:

use App\Models\Flight;

$flight = Flight::find(1);

$flight->name = 'Paris to London';

$flight->save();

既存のモデルを更新する時に、一致するモデルが存在しない場合は、新しいモデルを作成したい場合もあるでしょう。firstOrCreateメソッドと同様に、updateOrCreateメソッドはモデルを永続化するため、手作業でsaveメソッドを呼び出す必要はありません。Occasionally, you may need to update an existing model or create a new model if no matching model exists. Like the firstOrCreate method, the updateOrCreate method persists the model, so there's no need to manually call the save method.

以下の例では、Oaklandが「出発地(departure)」で、San Diegoが「目的地(destination)」のフライトが存在する場合、その「価格(price)」カラムと「割引(discounted)」カラムが更新されます。該当するフライトが存在しない場合は、最初の引数配列を2番目の引数配列とマージした結果の属性を持つ新しいフライトが作成されます。In the example below, if a flight exists with a departure location of Oakland and a destination location of San Diego, its price and discounted columns will be updated. If no such flight exists, a new flight will be created which has the attributes resulting from merging the first argument array with the second argument array:

$flight = Flight::updateOrCreate(
    ['departure' => 'Oakland', 'destination' => 'San Diego'],
    ['price' => 99, 'discounted' => 1]
);

複数更新Mass Updates

特定のクエリに一致するモデルに対して更新を実行することもできます。この例では、「アクティブ(active)」でdestinationSan Diegoのすべてのフライトが遅延(delayed)としてマークされます。Updates can also be performed against models that match a given query. In this example, all flights that are active and have a destination of San Diego will be marked as delayed:

Flight::where('active', 1)
      ->where('destination', 'San Diego')
      ->update(['delayed' => 1]);

updateメソッドは、更新する必要のあるカラムを表すカラム名と値のペアの配列を引数に取ります。updateメソッドは、影響を受けた行数を返します。The update method expects an array of column and value pairs representing the columns that should be updated. The update method returns the number of affected rows.

warning Warning! Eloquentを介して一括更新を発行する場合、更新されたモデルに対して、savingsavedupdatingupdatedモデルイベントは発生しません。これは一括更新を実行する場合に、モデルが実際には取得されないからです。[!WARNING]
When issuing a mass update via Eloquent, the saving, saved, updating, and updated model events will not be fired for the updated models. This is because the models are never actually retrieved when issuing a mass update.

属性の変更の判断Examining Attribute Changes

Eloquentでは、isDirtyisCleanwasChangedメソッドを提供しており、モデルの内部状態を調べ、モデルが最初に取得されたときからその属性がどのように変更されたかを判別できます。Eloquent provides the isDirty, isClean, and wasChanged methods to examine the internal state of your model and determine how its attributes have changed from when the model was originally retrieved.

isDirtyメソッドは、モデル取得後にそのモデルの属性が変更されたかを判定します。isDirtyメソッドに特定の属性名、あるいは属性の配列を渡せば、いずれかの属性に変更があったかを判定できます。isCleanメソッドは、モデル取得後、属性が変更されていないことを判定します。このメソッドはオプションのattribute引数も受け付けます。The isDirty method determines if any of the model's attributes have been changed since the model was retrieved. You may pass a specific attribute name or an array of attributes to the isDirty method to determine if any of the attributes are "dirty". The isClean method will determine if an attribute has remained unchanged since the model was retrieved. This method also accepts an optional attribute argument:

use App\Models\User;

$user = User::create([
    'first_name' => 'Taylor',
    'last_name' => 'Otwell',
    'title' => 'Developer',
]);

$user->title = 'Painter';

$user->isDirty(); // true
$user->isDirty('title'); // true
$user->isDirty('first_name'); // false
$user->isDirty(['first_name', 'title']); // true

$user->isClean(); // false
$user->isClean('title'); // false
$user->isClean('first_name'); // true
$user->isClean(['first_name', 'title']); // false

$user->save();

$user->isDirty(); // false
$user->isClean(); // true

wasChangedメソッドは現在のリクエストサイクル内で、モデルの最後の保存時に、属性に変更が起きたかを判別します。必要に応じ属性名を渡して、その属性に変更が発生したか確認できます。The wasChanged method determines if any attributes were changed when the model was last saved within the current request cycle. If needed, you may pass an attribute name to see if a particular attribute was changed:

$user = User::create([
    'first_name' => 'Taylor',
    'last_name' => 'Otwell',
    'title' => 'Developer',
]);

$user->title = 'Painter';

$user->save();

$user->wasChanged(); // true
$user->wasChanged('title'); // true
$user->wasChanged(['title', 'slug']); // true
$user->wasChanged('first_name'); // false
$user->wasChanged(['first_name', 'title']); // true

getOriginalメソッドは、モデル取得後の変更操作と関係なく、モデルの元の属性を含む配列を返します。必要に応じて、特定の属性名を渡し、その属性の元の値を取得できます。The getOriginal method returns an array containing the original attributes of the model regardless of any changes to the model since it was retrieved. If needed, you may pass a specific attribute name to get the original value of a particular attribute:

$user = User::find(1);

$user->name; // John
$user->email; // john@example.com

$user->name = "Jack";
$user->name; // Jack

$user->getOriginal('name'); // John
$user->getOriginal(); // 元の属性の配列

複数代入Mass Assignment

createメソッドを使用して、単一PHPステートメントで新しいモデルを「保存」できます。挿入したモデルインスタンスが、このメソッドにより返されます。You may use the create method to "save" a new model using a single PHP statement. The inserted model instance will be returned to you by the method:

use App\Models\Flight;

$flight = Flight::create([
    'name' => 'London to Paris',
]);

ただし、createメソッドを使用する前に、モデルクラスでfillableまたはguardedプロパティを指定する必要があります。すべてのEloquentモデルはデフォルトで複数代入の脆弱性から保護されているため、こうしたプロパティが必須になります。However, before using the create method, you will need to specify either a fillable or guarded property on your model class. These properties are required because all Eloquent models are protected against mass assignment vulnerabilities by default.

複数代入の脆弱性は、ユーザーから予期していないHTTPリクエストフィールドを渡され、そのフィールドがデータベース内の予想外のカラムを変更する場合に発生します。たとえば、悪意のあるユーザーがHTTPリクエストを介してis_adminパラメータを送信し、それがモデルのcreateメソッドに渡されて、ユーザーが自分自身を管理者に格上げする場合が考えられます。A mass assignment vulnerability occurs when a user passes an unexpected HTTP request field and that field changes a column in your database that you did not expect. For example, a malicious user might send an is_admin parameter through an HTTP request, which is then passed to your model's create method, allowing the user to escalate themselves to an administrator.

したがって、Eloquentを使い始めるには、複数代入可能にするモデル属性を定義する必要があります。これは、モデルの$fillableプロパティを使用して行います。たとえば、Flightモデルのname属性を一括割り当て可能にしましょう。So, to get started, you should define which model attributes you want to make mass assignable. You may do this using the $fillable property on the model. For example, let's make the name attribute of our Flight model mass assignable:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * 複数代入可能な属性
     *
     * @var array<int, string>
     */
    protected $fillable = ['name'];
}

複数代入可能な属性を指定したら、createメソッドを使用してデータベースに新しいレコードを挿入できます。createメソッドは、新しく作成したモデルインスタンスを返します。Once you have specified which attributes are mass assignable, you may use the create method to insert a new record in the database. The create method returns the newly created model instance:

$flight = Flight::create(['name' => 'London to Paris']);

モデルインスタンスがすでにある場合は、fillメソッドを使用して、属性の配列をセットできます。If you already have a model instance, you may use the fill method to populate it with an array of attributes:

$flight->fill(['name' => 'Amsterdam to Frankfurt']);

一括割り当てとJSONカラムMass Assignment and JSON Columns

JSONカラムへ代入するときは、各カラムの複数代入可能キーをモデルの$fillable配列で指定する必要があります。セキュリティのため、Laravelはguardedプロパティを使用する場合のネストしたJSON属性の更新をサポートしていません。When assigning JSON columns, each column's mass assignable key must be specified in your model's $fillable array. For security, Laravel does not support updating nested JSON attributes when using the guarded property:

/**
 * 複数代入可能な属性
 *
 * @var array<int, string>
 */
protected $fillable = [
    'options->enabled',
];

複数代入の許可Allowing Mass Assignment

すべての属性を一括割り当て可能にしたい場合は、モデルの$guardedプロパティを空の配列として定義します。モデルの保護を解除する場合は、Eloquentのfillcreate、およびupdateメソッドに渡たす配列へいちいち特別な注意を払う必要があります。If you would like to make all of your attributes mass assignable, you may define your model's $guarded property as an empty array. If you choose to unguard your model, you should take special care to always hand-craft the arrays passed to Eloquent's fill, create, and update methods:

/**
 * 複数代入不可能な属性
 *
 * @var array<string>|bool
 */
protected $guarded = [];

複数代入例外Mass Assignment Exceptions

複数代入操作を行うときデフォルトで、$fillable配列に含まれない属性は黙って破棄されます。実稼働環境でこれは期待されている動作です。しかし、ローカル開発時では、なぜモデルの変更が反映されないのか混乱させる可能性があります。By default, attributes that are not included in the $fillable array are silently discarded when performing mass-assignment operations. In production, this is expected behavior; however, during local development it can lead to confusion as to why model changes are not taking effect.

必要であれば、preventSilentlyDiscardingAttributesメソッドを呼び出し、複数代入不可の属性へ代入しようとした時に例外を投げるようにLaravelへ指示できます。通常、このメソッドはアプリケーションのAppServiceProviderクラスのbootメソッドで呼び出します。If you wish, you may instruct Laravel to throw an exception when attempting to fill an unfillable attribute by invoking the preventSilentlyDiscardingAttributes method. Typically, this method should be invoked in the boot method of your application's AppServiceProvider class:

use Illuminate\Database\Eloquent\Model;

/**
 * 全アプリケーションサービスの初期起動処理
 */
public function boot(): void
{
    Model::preventSilentlyDiscardingAttributes($this->app->isLocal());
}

更新/挿入Upserts

Eloquentのupsertメソッドを使用すると、単一で極小の操作でレコードを更新または作成できます。メソッドの最初の引数は挿入または更新する値で構成され、2番目の引数は関連テーブル内のレコードを一意に識別するカラムのリストです。メソッドの最後の引数である3番目の引数は、データベースに一致するレコードが既に存在する場合に更新するカラムの配列です。モデルでタイムスタンプが有効になっている場合、upsertメソッドは自動的にcreated_atupdated_atのタイムスタンプを設定します。Eloquent's upsert method may be used to update or create records in a single, atomic operation. The method's first argument consists of the values to insert or update, while the second argument lists the column(s) that uniquely identify records within the associated table. The method's third and final argument is an array of the columns that should be updated if a matching record already exists in the database. The upsert method will automatically set the created_at and updated_at timestamps if timestamps are enabled on the model:

Flight::upsert([
    ['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99],
    ['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150]
], uniqueBy: ['departure', 'destination'], update: ['price']);

warning Warning! SQL Server以外のすべてのデータベースでは、upsertメソッドの第2引数のカラムへ"primary"、または"unique"インデックスを指定する必要があります。さらに、MariaDBとMySQLデータベースドライバは、upsertメソッドの第2引数を無視し、常にテーブルの"primary"および"unique"インデックスを既存レコードの検出に使用します。[!WARNING]
All databases except SQL Server require the columns in the second argument of the upsert method to have a "primary" or "unique" index. In addition, the MariaDB and MySQL database drivers ignore the second argument of the upsert method and always use the "primary" and "unique" indexes of the table to detect existing records.

モデルの削除Deleting Models

モデルを削除するには、モデルインスタンスでdeleteメソッドを呼び出してください。To delete a model, you may call the delete method on the model instance:

use App\Models\Flight;

$flight = Flight::find(1);

$flight->delete();

モデルに関連しているすべてのデータベースレコードを削除するには、truncateメソッドを呼びだせます。truncate操作は、モデルの関連テーブルの自動増分IDをリセットします。You may call the truncate method to delete all of the model's associated database records. The truncate operation will also reset any auto-incrementing IDs on the model's associated table:

Flight::truncate();

主キーによる既存のモデルの削除Deleting an Existing Model by its Primary Key

上記の例では、deleteメソッドを呼び出す前にデータベースからモデルを取得しています。しかし、モデルの主キーがわかっている場合は、destroyメソッドを呼び出して、モデルを明示的に取得せずにモデルを削除できます。destroyメソッドは、単一の主キーを受け入れることに加えて、複数の主キー、主キーの配列、または主キーのコレクションを引数に取ります。In the example above, we are retrieving the model from the database before calling the delete method. However, if you know the primary key of the model, you may delete the model without explicitly retrieving it by calling the destroy method. In addition to accepting the single primary key, the destroy method will accept multiple primary keys, an array of primary keys, or a collection[/docs/{{version}}/collections] of primary keys:

Flight::destroy(1);

Flight::destroy(1, 2, 3);

Flight::destroy([1, 2, 3]);

Flight::destroy(collect([1, 2, 3]));

モデルのソフトデリートを利用している場合は、forceDestroyメソッドを使ってモデルを完全に削除できます。If you are utilizing soft deleting models[#soft-deleting], you may permanently delete models via the forceDestroy method:

Flight::forceDestroy(1);

warning Warning! destroyメソッドは各モデルを個別にロードし、deleteメソッドを呼び出して、deletingイベントとdeletedイベントが各モデルに適切にディスパッチされるようにします。[!WARNING]
The destroy method loads each model individually and calls the delete method so that the deleting and deleted events are properly dispatched for each model.

クエリを使用したモデルの削除Deleting Models Using Queries

もちろん、Eloquentクエリを作成して、クエリの条件に一致するすべてのモデルを削除することもできます。この例では、非アクティブとしてマークされているすべてのフライトを削除します。一括更新と同様に、一括削除では、削除されたモデルのモデルイベントはディスパッチされません。Of course, you may build an Eloquent query to delete all models matching your query's criteria. In this example, we will delete all flights that are marked as inactive. Like mass updates, mass deletes will not dispatch model events for the models that are deleted:

$deleted = Flight::where('active', 0)->delete();

warning Warning! Eloquentを介して一括削除ステートメントを実行すると、削除されたモデルに対してdeletingおよびdeletedモデルイベントがディスパッチされません。これは、deleteステートメントの実行時にモデルが実際には取得されないためです。[!WARNING]
When executing a mass delete statement via Eloquent, the deleting and deleted model events will not be dispatched for the deleted models. This is because the models are never actually retrieved when executing the delete statement.

ソフトデリートSoft Deleting

Eloquentは、データベースから実際にレコードを削除するだけでなく、モデルを「ソフトデリート」することもできます。モデルがソフトデリートされても、実際にはデータベースから削除されません。代わりに、モデルに「deleted_at」属性がセットされ、モデルを「削除」した日時が保存されます。モデルのソフトデリートを有効にするには、Illuminate\Database\Eloquent\SoftDeletesトレイトをモデルに追加します。In addition to actually removing records from your database, Eloquent can also "soft delete" models. When models are soft deleted, they are not actually removed from your database. Instead, a deleted_at attribute is set on the model indicating the date and time at which the model was "deleted". To enable soft deletes for a model, add the Illuminate\Database\Eloquent\SoftDeletes trait to the model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Flight extends Model
{
    use SoftDeletes;
}

lightbulb Note: SoftDeletesトレイトは、deleted_at属性をDateTime/Carbonインスタンスに自動的にキャストします。[!NOTE]
The SoftDeletes trait will automatically cast the deleted_at attribute to a DateTime / Carbon instance for you.

データベーステーブルにdeleted_atカラムを追加する必要があります。Laravelスキーマビルダはこのカラムを作成するためのヘルパメソッドを用意しています。You should also add the deleted_at column to your database table. The Laravel schema builder[/docs/{{version}}/migrations] contains a helper method to create this column:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('flights', function (Blueprint $table) {
    $table->softDeletes();
});

Schema::table('flights', function (Blueprint $table) {
    $table->dropSoftDeletes();
});

これで、モデルのdeleteメソッドを呼び出すと、deleted_at列が現在の日付と時刻に設定されます。ただし、モデルのデータベースレコードはテーブルに残ります。ソフトデリートを使用するモデルをクエリすると、ソフトデリートされたモデルはすべてのクエリ結果から自動的に除外されます。Now, when you call the delete method on the model, the deleted_at column will be set to the current date and time. However, the model's database record will be left in the table. When querying a model that uses soft deletes, the soft deleted models will automatically be excluded from all query results.

特定のモデルインスタンスがソフトデリートされているかを判断するには、trashedメソッドを使用します。To determine if a given model instance has been soft deleted, you may use the trashed method:

if ($flight->trashed()) {
    // ...
}

ソフトデリートしたモデルの復元Restoring Soft Deleted Models

ソフトデリートしたモデルを「削除解除」したい場合もあるでしょう。ソフトデリートしたモデルを復元するには、モデルインスタンスのrestoreメソッドを呼び出します。restoreメソッドは、モデルのdeleted_atカラムをnullにセットします。Sometimes you may wish to "un-delete" a soft deleted model. To restore a soft deleted model, you may call the restore method on a model instance. The restore method will set the model's deleted_at column to null:

$flight->restore();

クエリでrestoreメソッドを使用して、複数のモデルを復元することもできます。繰り返しますが、他の「複数」操作と同様に、これは復元されたモデルのモデルイベントをディスパッチしません。You may also use the restore method in a query to restore multiple models. Again, like other "mass" operations, this will not dispatch any model events for the models that are restored:

Flight::withTrashed()
        ->where('airline_id', 1)
        ->restore();

restoreメソッドは、リレーションのクエリを作成するときにも使用できます。The restore method may also be used when building relationship[/docs/{{version}}/eloquent-relationships] queries:

$flight->history()->restore();

モデルの完全な削除Permanently Deleting Models

データベースからモデルを本当に削除する必要が起きる場合もあるでしょう。forceDeleteメソッドを使用して、データベーステーブルからソフトデリートされたモデルを完全に削除できます。Sometimes you may need to truly remove a model from your database. You may use the forceDelete method to permanently remove a soft deleted model from the database table:

$flight->forceDelete();

Eloquentリレーションクエリを作成するときに、forceDeleteメソッドを使用することもできます。You may also use the forceDelete method when building Eloquent relationship queries:

$flight->history()->forceDelete();

ソフトデリート済みモデルのクエリQuerying Soft Deleted Models

ソフトデリートモデルを含めるIncluding Soft Deleted Models

上記のように、ソフトデリートしたモデルはクエリ結果から自動的に除外されます。ただし、クエリでwithTrashedメソッドを呼び出すことにより、ソフトデリートしたモデルをクエリの結果に含められます。As noted above, soft deleted models will automatically be excluded from query results. However, you may force soft deleted models to be included in a query's results by calling the withTrashed method on the query:

use App\Models\Flight;

$flights = Flight::withTrashed()
                ->where('account_id', 1)
                ->get();

withTrashedメソッドは、リレーションクエリを作成するときにも呼び出すことができます。The withTrashed method may also be called when building a relationship[/docs/{{version}}/eloquent-relationships] query:

$flight->history()->withTrashed()->get();

ソフトデリートモデルのみを取得するRetrieving Only Soft Deleted Models

onlyTrashedメソッドは、ソフトデリートしたモデルのみ取得します。The onlyTrashed method will retrieve only soft deleted models:

$flights = Flight::onlyTrashed()
                ->where('airline_id', 1)
                ->get();

モデルの整理Pruning Models

不要になったモデルを定期的に削除したい場合があります。これを実現するには、定期的に整理したいモデルに、Illuminate\Database\Eloquent\PrunableIlluminate\Database\Eloquent\MassPrunableトレイトを追加してください。モデルにどちらかのトレイトを追加したら、不要なモデルを指定するEloquentのクエリビルダを返すprunableメソッドを実装します。Sometimes you may want to periodically delete models that are no longer needed. To accomplish this, you may add the Illuminate\Database\Eloquent\Prunable or Illuminate\Database\Eloquent\MassPrunable trait to the models you would like to periodically prune. After adding one of the traits to the model, implement a prunable method which returns an Eloquent query builder that resolves the models that are no longer needed:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Prunable;

class Flight extends Model
{
    use Prunable;

    /**
     * 整理可能モデルクエリの取得
     */
    public function prunable(): Builder
    {
        return static::where('created_at', '<=', now()->subMonth());
    }
}

Prunableとしてモデルを作成する際に、そのモデルへpruningメソッドを定義することもできます。このメソッドはモデルが削除される前に呼び出されます。このメソッドは、モデルがデータベースから永久に削除される前に、保存しているファイルなど、モデルに関連する追加リソースを削除するために役立ちます。When marking models as Prunable, you may also define a pruning method on the model. This method will be called before the model is deleted. This method can be useful for deleting any additional resources associated with the model, such as stored files, before the model is permanently removed from the database:

/**
 * 整理可能モデルの準備
 */
protected function pruning(): void
{
    // ...
}

整理可能なモデルを設定した後、アプリケーションのroutes/console.phpファイルでmodel:prune Artisanコマンドをスケジュールする必要があります。このコマンドを実行する適切な間隔は自由に選べます。After configuring your prunable model, you should schedule the model:prune Artisan command in your application's routes/console.php file. You are free to choose the appropriate interval at which this command should be run:

use Illuminate\Support\Facades\Schedule;

Schedule::command('model:prune')->daily();

model:pruneコマンドは、裏でアプリケーションのapp/Modelsディレクトリ内にある、"Prunable"モデルを自動的に検出します。モデルが別の場所にある場合は、--modelオプションを使って、モデルクラス名を指定できます。Behind the scenes, the model:prune command will automatically detect "Prunable" models within your application's app/Models directory. If your models are in a different location, you may use the --model option to specify the model class names:

Schedule::command('model:prune', [
    '--model' => [Address::class, Flight::class],
])->daily();

検出したすべてのモデルを整理する場合に、特定のモデルを除外したい場合は、--exceptオプションを使用します。If you wish to exclude certain models from being pruned while pruning all other detected models, you may use the --except option:

Schedule::command('model:prune', [
    '--except' => [Address::class, Flight::class],
])->daily();

model:pruneコマンドを--pretendオプション付きで実行することで、prunableクエリをテストできます。このオプションを付けると、model:pruneコマンドが実際にコマンドを実行する場合、いくつのレコードを整理するかだけを報告します。You may test your prunable query by executing the model:prune command with the --pretend option. When pretending, the model:prune command will simply report how many records would be pruned if the command were to actually run:

php artisan model:prune --pretend

warning Warning! Prunableクエリに一致した場合、ソフトデリートするモデルでも、永久的に削除(forceDelete)します。[!WARNING]
Soft deleting models will be permanently deleted (forceDelete) if they match the prunable query.

複数整理Mass Pruning

モデルへIlluminate\Database\Eloquent\MassPrunableトレイトが付与されると、モデルは複数削除クエリを使ってデータベースから削除されます。そのため、pruningメソッドを呼び出しませんし、deletingdeletedのモデルイベントも発行しません。これはモデルの削除前で実際に取得しないため、整理処理をより効率的に行うことができるからです。When models are marked with the Illuminate\Database\Eloquent\MassPrunable trait, models are deleted from the database using mass-deletion queries. Therefore, the pruning method will not be invoked, nor will the deleting and deleted model events be dispatched. This is because the models are never actually retrieved before deletion, thus making the pruning process much more efficient:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\MassPrunable;

class Flight extends Model
{
    use MassPrunable;

    /**
     * 整理可能モデルクエリの取得
     */
    public function prunable(): Builder
    {
        return static::where('created_at', '<=', now()->subMonth());
    }
}

モデルの複製Replicating Models

replicateメソッドを使用して、既存のモデルインスタンスの未保存のコピーを作成できます。この方法は、同じ属性を多く共有するモデルインスタンスがある場合にとくに役立ちます。You may create an unsaved copy of an existing model instance using the replicate method. This method is particularly useful when you have model instances that share many of the same attributes:

use App\Models\Address;

$shipping = Address::create([
    'type' => 'shipping',
    'line_1' => '123 Example Street',
    'city' => 'Victorville',
    'state' => 'CA',
    'postcode' => '90001',
]);

$billing = $shipping->replicate()->fill([
    'type' => 'billing'
]);

$billing->save();

1つ以上の属性を新しいモデルへ複製しないためには、配列をreplicateメソッドへ渡します。To exclude one or more attributes from being replicated to the new model, you may pass an array to the replicate method:

$flight = Flight::create([
    'destination' => 'LAX',
    'origin' => 'LHR',
    'last_flown' => '2020-03-04 11:00:00',
    'last_pilot_id' => 747,
]);

$flight = $flight->replicate([
    'last_flown',
    'last_pilot_id'
]);

クエリスコープQuery Scopes

グローバルスコープGlobal Scopes

グローバルスコープを使用すると、特定のモデルのすべてのクエリに制約を追加できます。Laravel独自のソフトデリート機能は、グローバルスコープを利用してデータベースから「削除していない」モデルのみを取得します。独自のグローバルスコープを作成すれば、指定したモデルですべてのクエリが同じ制約を受けるようにする、便利で簡単な方法が利用できます。Global scopes allow you to add constraints to all queries for a given model. Laravel's own soft delete[#soft-deleting] functionality utilizes global scopes to only retrieve "non-deleted" models from the database. Writing your own global scopes can provide a convenient, easy way to make sure every query for a given model receives certain constraints.

スコープの生成Generating Scopes

新しいグローバルスコープを生成するには、make:scope Artisanコマンドを呼び出してください。生成したスコープは、アプリケーションのapp/Models/Scopesディレクトリへ設置します。To generate a new global scope, you may invoke the make:scope Artisan command, which will place the generated scope in your application's app/Models/Scopes directory:

php artisan make:scope AncientScope

グローバルスコープの作成Writing Global Scopes

グローバルスコープを書くのは簡単です。まず、make:scopeコマンドを使いIlluminate\Database\Eloquent\Scopeインターフェイスを実装したクラスを生成します。Scopeインターフェイスは、applyメソッド1つの実装を求めています。必要に応じapplyメソッドへ、where制約や他のタイプの句をクエリへ追加してください。Writing a global scope is simple. First, use the make:scope command to generate a class that implements the Illuminate\Database\Eloquent\Scope interface. The Scope interface requires you to implement one method: apply. The apply method may add where constraints or other types of clauses to the query as needed:

<?php

namespace App\Models\Scopes;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;

class AncientScope implements Scope
{
    /**
     * 指定のEloquentクエリビルダにスコープを適用
     */
    public function apply(Builder $builder, Model $model): void
    {
        $builder->where('created_at', '<', now()->subYears(2000));
    }
}

lightbulb Note: グローバルスコープがクエリのSELECT句にカラムを追加する場合は、selectの代わりにaddSelectメソッドを使用する必要があります。これにより、クエリの既存のselect句が意図せず置き換えられるのを防ぐことができます。[!NOTE]
If your global scope is adding columns to the select clause of the query, you should use the addSelect method instead of select. This will prevent the unintentional replacement of the query's existing select clause.

グローバルスコープの適用Applying Global Scopes

モデルにグローバルスコープを割り当てるには、モデルへScopedByアトリビュートを指定します。To assign a global scope to a model, you may simply place the ScopedBy attribute on the model:

<?php

namespace App\Models;

use App\Models\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Attributes\ScopedBy;

#[ScopedBy([AncientScope::class])]
class User extends Model
{
    //
}

あるいは、モデルのbootedメソッドをオーバーライドして、モデルのaddGlobalScopeメソッドを呼び出せば、手作業でグローバルスコープを登録することも可能です。addGlobalScopeメソッドは、唯一スコープのインスタンスを引数に取ります。Or, you may manually register the global scope by overriding the model's booted method and invoke the model's addGlobalScope method. The addGlobalScope method accepts an instance of your scope as its only argument:

<?php

namespace App\Models;

use App\Models\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * モデルの"booted"メソッド
     */
    protected static function booted(): void
    {
        static::addGlobalScope(new AncientScope);
    }
}

上記の例のスコープをApp\Models\Userモデルに追加した後、User::all()メソッドを呼び出すと、次のSQLクエリが実行されます。After adding the scope in the example above to the App\Models\User model, a call to the User::all() method will execute the following SQL query:

select * from `users` where `created_at` < 0021-02-18 00:00:00

匿名のグローバルスコープAnonymous Global Scopes

Eloquentはクロージャを使用してグローバルスコープを定義することもできます。クロージャを使用してグローバルスコープを定義する場合は、addGlobalScopeメソッドの第一引数に自分で選択したスコープ名を指定する必要があります。Eloquent also allows you to define global scopes using closures, which is particularly useful for simple scopes that do not warrant a separate class of their own. When defining a global scope using a closure, you should provide a scope name of your own choosing as the first argument to the addGlobalScope method:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * モデルの"booted"メソッド
     */
    protected static function booted(): void
    {
        static::addGlobalScope('ancient', function (Builder $builder) {
            $builder->where('created_at', '<', now()->subYears(2000));
        });
    }
}

グローバルスコープの削除Removing Global Scopes

特定のクエリのグローバルスコープを削除する場合は、withoutGlobalScopeメソッドを使用できます。このメソッドは、グローバルスコープのクラス名だけを引数に取ります。If you would like to remove a global scope for a given query, you may use the withoutGlobalScope method. This method accepts the class name of the global scope as its only argument:

User::withoutGlobalScope(AncientScope::class)->get();

もしくは、クロージャを使用してグローバルスコープを定義した場合は、グローバルスコープへ指定した文字列名を渡す必要があります。Or, if you defined the global scope using a closure, you should pass the string name that you assigned to the global scope:

User::withoutGlobalScope('ancient')->get();

クエリのグローバルスコープのいくつか、またはすべてを削除したい場合は、withoutGlobalScopesメソッドを使用できます。If you would like to remove several or even all of the query's global scopes, you may use the withoutGlobalScopes method:

// すべてのグローバルスコープを削除
User::withoutGlobalScopes()->get();

// グローバルスコープの一部を削除
User::withoutGlobalScopes([
    FirstScope::class, SecondScope::class
])->get();

ローカルスコープLocal Scopes

ローカルスコープを使用すると、アプリケーション全体で簡単に再利用できる、共通のクエリ制約を定義できます。たとえば、「人気がある(popular)」と思われるすべてのユーザーを頻繁に取得する必要があるとしましょう。スコープを定義するには、Eloquentモデルメソッドの前にscopeを付けます。Local scopes allow you to define common sets of query constraints that you may easily re-use throughout your application. For example, you may need to frequently retrieve all users that are considered "popular". To define a scope, prefix an Eloquent model method with scope.

スコープは常に同じクエリビルダのインスタンスか、voidを返す必要があります。Scopes should always return the same query builder instance or void:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 人気のあるユーザーのみを含むようにクエリのスコープを設定
     */
    public function scopePopular(Builder $query): void
    {
        $query->where('votes', '>', 100);
    }

    /**
     * アクティブユーザーのみを含むようにクエリのスコープを設定
     */
    public function scopeActive(Builder $query): void
    {
        $query->where('active', 1);
    }
}

ローカルスコープの利用Utilizing a Local Scope

スコープを定義したら、モデルをクエリするときにスコープメソッドを呼び出すことができます。ただし、メソッドを呼び出すときにscopeプレフィックスを含めないでください。さまざまなスコープに呼び出しをチェーンすることもできます。Once the scope has been defined, you may call the scope methods when querying the model. However, you should not include the scope prefix when calling the method. You can even chain calls to various scopes:

use App\Models\User;

$users = User::popular()->active()->orderBy('created_at')->get();

orクエリ演算子を介して複数のEloquentモデルスコープを組み合わせるには、正しい論理グループ化を実現するためにクロージャを使用する必要のある場合があります。Combining multiple Eloquent model scopes via an or query operator may require the use of closures to achieve the correct logical grouping[/docs/{{version}}/queries#logical-grouping]:

$users = User::popular()->orWhere(function (Builder $query) {
    $query->active();
})->get();

ただし、これは面倒な場合があるため、Laravelは、クロージャを使用せずにスコープを流暢にチェーンできる「高次」の「orWhere」メソッドを提供しています。However, since this can be cumbersome, Laravel provides a "higher order" orWhere method that allows you to fluently chain scopes together without the use of closures:

$users = User::popular()->orWhere->active()->get();

動的スコープDynamic Scopes

パラメータを受け入れるスコープを定義したい場合もあるでしょう。使用するには、スコープメソッドの引数にパラメータを追加するだけです。スコープパラメータは、$queryパラメータの後に定義する必要があります。Sometimes you may wish to define a scope that accepts parameters. To get started, just add your additional parameters to your scope method's signature. Scope parameters should be defined after the $query parameter:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 特定のタイプのユーザーのみを含むようにクエリのスコープを設定
     */
    public function scopeOfType(Builder $query, string $type): void
    {
        $query->where('type', $type);
    }
}

期待される引数をスコープメソッドの引数へ追加したら、スコープ呼び出し時に引数を渡すことができます。Once the expected arguments have been added to your scope method's signature, you may pass the arguments when calling the scope:

$users = User::ofType('admin')->get();

モデルの比較Comparing Models

2つのモデルが「同じ」であるかを判定する必要がある場合があるでしょう。2つのモデルに同じ主キー、テーブル、およびデータベース接続があるかどうかを手早く検証するために、isisNotメソッドを使用できます。Sometimes you may need to determine if two models are the "same" or not. The is and isNot methods may be used to quickly verify two models have the same primary key, table, and database connection or not:

if ($post->is($anotherPost)) {
    // ...
}

if ($post->isNot($anotherPost)) {
    // ...
}

isisNotメソッドは、belongsTohasOnemorphTomorphOneリレーションを使用するときにも利用できます。このメソッドはそのモデルを取得するためにクエリを発行せず、関連モデルと比較したい場合、特に役立ちます。The is and isNot methods are also available when using the belongsTo, hasOne, morphTo, and morphOne relationships[/docs/{{version}}/eloquent-relationships]. This method is particularly helpful when you would like to compare a related model without issuing a query to retrieve that model:

if ($post->author()->is($user)) {
    // ...
}

イベントEvents

lightbulb Note: Eloquentのイベントをクライアントサイドのアプリケーションへ直接ブロードキャストしたいですか?Laravelのモデル・イベント・ブロードキャストをチェックしてください。[!NOTE]
Want to broadcast your Eloquent events directly to your client-side application? Check out Laravel's model event broadcasting[/docs/{{version}}/broadcasting#model-broadcasting].

Eloquentモデルはいくつかのイベントをディスパッチし、モデルのライフサイクルの以下の瞬間をフックできるようにしています。:retrievedcreatingcreatedupdatingupdatedsavingsaveddeletingdeletedtrashedforceDeletingforceDeletedrestoringrestoredreplicatingEloquent models dispatch several events, allowing you to hook into the following moments in a model's lifecycle: retrieved, creating, created, updating, updated, saving, saved, deleting, deleted, trashed, forceDeleting, forceDeleted, restoring, restored, and replicating.

retrievedイベントは、既存のモデルをデータベースから取得したときにディスパッチします。新しいモデルをはじめて保存するときは、creatingイベントとcreatedイベントをディスパッチします。updatingupdatedイベントは、既存のモデルを変更し、saveメソッドが呼び出されたときにディスパッチします。savingsavedイベントは、モデルを作成または更新したときにディスパッチします。モデルの属性に変化がない場合でも、ディスパッチします。イベント名が-ingで終わるイベントは、モデルへの変更が永続化される前にディスパッチされ、-edで終わるイベントは、モデルへの変更が永続化された後にディスパッチされます。The retrieved event will dispatch when an existing model is retrieved from the database. When a new model is saved for the first time, the creating and created events will dispatch. The updating / updated events will dispatch when an existing model is modified and the save method is called. The saving / saved events will dispatch when a model is created or updated - even if the model's attributes have not been changed. Event names ending with -ing are dispatched before any changes to the model are persisted, while events ending with -ed are dispatched after the changes to the model are persisted.

モデルイベントのリッスンを開始するには、Eloquentモデルで$dispatchesEventsプロパティを定義します。このプロパティは、Eloquentモデルのライフサイクルのさまざまなポイントを独自のイベントクラスにマップします。各モデルイベントクラスはコンストラクターにより、影響を受けるモデルのインスタンスを引数に受け取ります。To start listening to model events, define a $dispatchesEvents property on your Eloquent model. This property maps various points of the Eloquent model's lifecycle to your own event classes[/docs/{{version}}/events]. Each model event class should expect to receive an instance of the affected model via its constructor:

<?php

namespace App\Models;

use App\Events\UserDeleted;
use App\Events\UserSaved;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * モデルのイベントマップ
     *
     * @var array<string, string>
     */
    protected $dispatchesEvents = [
        'saved' => UserSaved::class,
        'deleted' => UserDeleted::class,
    ];
}

Eloquentイベントを定義してマッピングした後は、そのイベントを処理するためにイベントリスナを使用します。After defining and mapping your Eloquent events, you may use event listeners[/docs/{{version}}/events#defining-listeners] to handle the events.

warning Warning! Eloquentを介して一括更新または削除クエリを発行する場合、影響を受けるモデルに対して、savedupdateddeletingdeletedモデルイベントをディスパッチしません。これは、一括更新または一括削除を実行するときにモデルを実際に取得しないためです。[!WARNING]
When issuing a mass update or delete query via Eloquent, the saved, updated, deleting, and deleted model events will not be dispatched for the affected models. This is because the models are never actually retrieved when performing mass updates or deletes.

クロージャの使用Using Closures

カスタムイベントクラスを使用する代わりに、さまざまなモデルイベントがディスパッチされたときに実行するクロージャを登録できます。通常、これらのクロージャはモデルの「booted」メソッドで登録する必要があります。Instead of using custom event classes, you may register closures that execute when various model events are dispatched. Typically, you should register these closures in the booted method of your model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * モデルの"booted"メソッド
     */
    protected static function booted(): void
    {
        static::created(function (User $user) {
            // ...
        });
    }
}

必要に応じて、モデルイベントを登録するときに、キュー投入可能な匿名イベントリスナを利用できます。これにより、アプリケーションのキューを使用し、バックグラウンドでモデルイベントリスナを実行するようにLaravelに指示できます。If needed, you may utilize queueable anonymous event listeners[/docs/{{version}}/events#queuable-anonymous-event-listeners] when registering model events. This will instruct Laravel to execute the model event listener in the background using your application's queue[/docs/{{version}}/queues]:

use function Illuminate\Events\queueable;

static::created(queueable(function (User $user) {
    // ...
}));

オブザーバObservers

オブザーバの定義Defining Observers

特定のモデルで多くのイベントをリッスンしている場合は、オブザーバを使用してすべてのリスナを1つのクラスにグループ化できます。オブザーバクラスは、リッスンするEloquentイベントを反映するメソッド名を持っています。これらの各メソッドは、唯一影響を受けるモデルを引数に取ります。make:observer Artisanコマンドは、新しいオブザーバクラスを作成するもっとも簡単な方法です。If you are listening for many events on a given model, you may use observers to group all of your listeners into a single class. Observer classes have method names which reflect the Eloquent events you wish to listen for. Each of these methods receives the affected model as their only argument. The make:observer Artisan command is the easiest way to create a new observer class:

php artisan make:observer UserObserver --model=User

このコマンドは、新しいオブザーバをapp/Observersディレクトリに配置します。このディレクトリが存在しない場合は、Artisanが作成します。新しいオブザーバは以下のようになります。This command will place the new observer in your app/Observers directory. If this directory does not exist, Artisan will create it for you. Your fresh observer will look like the following:

<?php

namespace App\Observers;

use App\Models\User;

class UserObserver
{
    /**
     * ユーザーの"created"イベントの処理
     */
    public function created(User $user): void
    {
        // ...
    }

    /**
     * ユーザーの"updated"イベントの処理
     */
    public function updated(User $user): void
    {
        // ...
    }

    /**
     * ユーザーの"deleted"イベントの処理
     */
    public function deleted(User $user): void
    {
        // ...
    }

    /**
     * ユーザーの"restored"イベントの処理
     */
    public function restored(User $user): void
    {
        // ...
    }

    /**
     * ユーザーの"forceDeleted"イベントの処理
     */
    public function forceDeleted(User $user): void
    {
        // ...
    }
}

オブザーバを登録するには、対応するモデルへObservedByアトリビュートを指定します。To register an observer, you may place the ObservedBy attribute on the corresponding model:

use App\Observers\UserObserver;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;

#[ObservedBy([UserObserver::class])]
class User extends Authenticatable
{
    //
}

あるいは、監視したいモデルに対し、observeメソッドを呼び出し、手作業でオブザーバを登録することもできます。アプリケーションのAppServiceProviderクラスのbootメソッドでオブザーバを登録してください。Or, you may manually register an observer by invoking the observe method on the model you wish to observe. You may register observers in the boot method of your application's AppServiceProvider class:

use App\Models\User;
use App\Observers\UserObserver;

/**
 * 全アプリケーションサービスの初期起動処理
 */
public function boot(): void
{
    User::observe(UserObserver::class);
}

lightbulb Note: オブザーバがリッスンできる他のイベントには、savingretrievedなどがあります。こうしたイベントについては、イベントのドキュメントで説明しています。[!NOTE]
There are additional events an observer can listen to, such as saving and retrieved. These events are described within the events[#events] documentation.

オブザーバとデータベーストランザクションObservers and Database Transactions

データベーストランザクション内でモデルを作成している場合、データベーストランザクションがコミットされた後にのみイベントハンドラを実行するようにオブザーバへ指示したい場合があるでしょう。これを実現するには、オブザーバでShouldHandleEventsAfterCommitインターフェイスを実装します。データベーストランザクションが進行中でなければ、イベントハンドラは直ちに実行されます。When models are being created within a database transaction, you may want to instruct an observer to only execute its event handlers after the database transaction is committed. You may accomplish this by implementing the ShouldHandleEventsAfterCommit interface on your observer. If a database transaction is not in progress, the event handlers will execute immediately:

<?php

namespace App\Observers;

use App\Models\User;
use Illuminate\Contracts\Events\ShouldHandleEventsAfterCommit;

class UserObserver implements ShouldHandleEventsAfterCommit
{
    /**
     * ユーザーの"created"イベントの処理
     */
    public function created(User $user): void
    {
        // ...
    }
}

イベントのミュートMuting Events

モデルにより発生するすべてのイベントを一時的に「ミュート」したい場合が起こりえます。実現するには、withoutEventsメソッドを使います。withoutEventsメソッドは、クロージャを唯一の引数として取ります。このクロージャ内で実行するコードはモデルイベントを発行させず、クロージャが返す値はすべてwithoutEventsメソッドが返します。You may occasionally need to temporarily "mute" all events fired by a model. You may achieve this using the withoutEvents method. The withoutEvents method accepts a closure as its only argument. Any code executed within this closure will not dispatch model events, and any value returned by the closure will be returned by the withoutEvents method:

use App\Models\User;

$user = User::withoutEvents(function () {
    User::findOrFail(1)->delete();

    return User::find(2);
});

イベントなしの単一モデル保存Saving a Single Model Without Events

イベントをディスパッチせずに、特定のモデルを「保存」したい場合があります。その場合は、saveQuietlyメソッドを使用してください。Sometimes you may wish to "save" a given model without dispatching any events. You may accomplish this using the saveQuietly method:

$user = User::findOrFail(1);

$user->name = 'Victoria Faith';

$user->saveQuietly();

また、イベントをディスパッチせずに、与えられたモデルを「更新(update)」、「削除(delete)」、「ソフトデリート(soft delete)」、「復元(restore)」、「複製(replicate)」できます。You may also "update", "delete", "soft delete", "restore", and "replicate" a given model without dispatching any events:

$user->deleteQuietly();
$user->forceDeleteQuietly();
$user->restoreQuietly();

章選択

設定

明暗テーマ
light_mode
dark_mode
brightness_auto システム設定に合わせる
テーマ選択
photo_size_select_actual デフォルト
photo_size_select_actual モノクローム(白黒)
photo_size_select_actual Solarized風
photo_size_select_actual GitHub風(青ベース)
photo_size_select_actual Viva(黄緑ベース)
photo_size_select_actual Happy(紫ベース)
photo_size_select_actual Mint(緑ベース)
コードハイライトテーマ選択

明暗テーマごとに、コードハイライトのテーマを指定できます。

テーマ配色確認
スクリーン表示幅
640px
80%
90%
100%

768px以上の幅があるときのドキュメント部分表示幅です。

インデント
無し
1rem
2rem
3rem
原文確認
原文を全行表示
原文を一行ずつ表示
使用しない

※ 段落末のEボタンへカーソルオンで原文をPopupします。

Diff表示形式
色分けのみで区別
行頭の±で区別
削除線と追記で区別

※ [tl!…]形式の挿入削除行の表示形式です。

テストコード表示
両コード表示
Pestのみ表示
PHPUnitのみ表示
OS表示
全OS表示
macOSのみ表示
windowsのみ表示
linuxのみ表示
和文変換

対象文字列と置換文字列を半角スペースで区切ってください。(最大5組各10文字まで)

本文フォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

コードフォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

保存内容リセット

localStrageに保存してある設定項目をすべて削除し、デフォルト状態へ戻します。

ヘッダー項目移動

キーボード操作