イントロダクションIntroduction
Eloquent ORMはLaravelに含まれている、美しくシンプルなアクティブレコードによるデーター操作の実装です。それぞれのデータベーステーブルは関連する「モデル」と結びついています。The Eloquent ORM included with Laravel provides a beautiful, simple ActiveRecord implementation for working with your database. Each database table has a corresponding "Model" which is used to interact with that table.
使用を始める前に、cofig/database.php
の設定を確実に済ませて置いてください。Before getting started, be sure to configure a database connection in config/database.php
.
基本的な使用法Basic Usage
使いはじめるには、まずEloquentモデルを作成しましょう。通常、モデルはapp
ディレクトリー下に置きますが、composer.json
ファイルでオートロードするように指定した場所であれば、どこでも自由に設置できます。全てのEloquentモデルは、Illuminate\Database\Eloquent\Model
を拡張する必要があります。To get started, create an Eloquent model. Models typically live in the app
directory, but you are free to place them anywhere that can be auto-loaded according to your composer.json
file. All Eloquent models extend Illuminate\Database\Eloquent\Model
.
Eloquentモデルの定義Defining An Eloquent Model
class User extends Model {}
また、make:model
コマンドを使用し、Eloquentモデルを生成することもできます。You may also generate Eloquent models using the make:model
command:
php artisan make:model User
User
モデルにどのテーブルを使用するか、Eloquentに指定していない点に注目してください。クラス名を複数形のスネークケースにしたものがテーブル名として使用されます。今回の例でEloquentは、User
モデルをusers
テーブルに保存します。他の名前を使用したい場合は明示的に指定します。モデルのtable
プロパティを定義し、テーブル名を指定します。Note that we did not tell Eloquent which table to use for our User
model. 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 User
model stores records in the users
table. You may specify a custom table by defining a table
property on your model:
class User extends Model {
protected $table = 'my_users';
}
注目: Eloquentは更にテーブルの主キーが、
id
というカラム名であると想定しています。この規約をオーバーライドする場合はprimaryKey
プロパティを定義してください。同様に、connection
プロパティを定義することで、そのモデルを取り扱うデータベース接続をオーバーライドすることもできます。Note: Eloquent will also assume that each table has a primary key column namedid
. You may define aprimaryKey
property to override this convention. Likewise, you may define aconnection
property to override the name of the database connection that should be used when utilizing the model.
一度モデルを定義したら、テーブルのレコードを取得したり、作成したりする準備は整いました。デフォルトではupdated_at
(更新時間)とcreated_at
(作成時間)カラムをテーブルに用意しておく必要があることに注意してください。これらのカラムを自動的に更新したくないなら、$timestamps
をfalse
に設定してください。Once a model is defined, you are ready to start retrieving and creating records in your table. Note that you will need to place updated_at
and created_at
columns on your table by default. If you do not wish to have these columns automatically maintained, set the $timestamps
property on your model to false
.
全レコードの取得Retrieving All Records
$users = User::all();
主キーから1レコードを取得Retrieving A Record By Primary Key
$user = User::find(1);
var_dump($user->name);
クエリービルダーの全メソッドは、Eloquentモデルを使ってクエリーする場合に使用できます。Note: All methods available on the query builder[/docs/queries] are also available when querying Eloquent models.
主キーでモデルを取得、もしくは例外を投げるRetrieving A Model By Primary Key Or Throw An Exception
モデルが見つからない場合、例外を投げたいこともあることでしょう。firstOrFail
メソッドを使用してください。Sometimes you may wish to throw an exception if a model is not found. To do this, you may use the firstOrFail
method:
$model = User::findOrFail(1);
$model = User::where('votes', '>', 100)->firstOrFail();
例外を捉え、必要に応じログを取るなり、エラーページを表示するなりできます。ModelNotFoundException
例外を補足するには、ファイルにロジックを追加します。Doing this will let you catch the exception so you can log and display an error page as necessary. To catch the ModelNotFoundException
, add some logic to your app/Exceptions/Handler.php
file.
use Illuminate\Database\Eloquent\ModelNotFoundException;
class Handler extends ExceptionHandler {
public function render($request, Exception $e)
{
if ($e instanceof ModelNotFoundException)
{
// モデルが見つからない場合のカスタムロジック
}
return parent::render($request, $e);
}
}
Eloquentモデルを使用したクエリーQuerying Using Eloquent Models
$users = User::where('votes', '>', 100)->take(10)->get();
foreach ($users as $user)
{
var_dump($user->name);
}
Eloquentを使った集計Eloquent Aggregates
もちろんクエリービルダーの集計関数も使用できます。Of course, you may also use the query builder aggregate functions.
$count = User::where('votes', '>', 100)->count();
Fluentインターフェイスで必要なクエリーを生成できない場合、whereRaw
を使用してください。If you are unable to generate the query you need via the fluent interface, feel free to use whereRaw
:
$users = User::whereRaw('age > ? and votes = 100', [25])->get();
結果の分割Chunking Results
大きな(数千の)Eloquentレコードを処理する必要がある場合、RAMが食いつぶされないように、chunk
コマンドを利用してください。If you need to process a lot (thousands) of Eloquent records, using the chunk
command will allow you to do without eating all of your RAM:
User::chunk(200, function($users)
{
foreach ($users as $user)
{
//
}
});
最初の引数には「チャンク(塊)」ごとにいくつのレコードを処理するかを渡します。2番めの引数にはクロージャーを渡し、そのデータベースからの結果をチャンクごとに処理するコードを記述します。The first argument passed to the method is the number of records you wish to receive per "chunk". The Closure passed as the second argument will be called for each chunk that is pulled from the database.
クエリー接続の指定Specifying The Query Connection
Eloquentクエリーの実行時に、データベース接続を指定することができます。on
メソッドを使用してください。You may also specify which database connection should be used when running an Eloquent query. Simply use the on
method:
$user = User::on('connection-name')->find(1);
Read/Write接続を利用している場合に、"write"接続で強制的にクエリーする場合は、以下のメソッドを使用してください。If you are using read / write connections[/docs/{{version}}/database#read-write-connections], you may force the query to use the "write" connection with the following method:
$user = User::onWriteConnection()->find(1);
複数代入Mass Assignment
新しいモデルを作成する時、モデルのコンストラクターに属性の配列を渡せます。渡した属性は、複数代入としてモデルに結び付けられます。これは便利ですが、ユーザーの入力を闇雲にモデルに渡してしまうことは、重大なセキュリティーの欠陥になり得ます。何でもかんでもユーザー入力をモデルに渡せば、ユーザーは何でもかんでもモデルの全属性を変更できるのです。このため、全てのEloquentモデルは複数代入されないよう、デフォルトとして保護されています。When creating a new model, you pass an array of attributes to the model constructor. These attributes are then assigned to the model via mass-assignment. This is convenient; however, can be a serious security concern when blindly passing user input into a model. If user input is blindly passed into a model, the user is free to modify any and all of the model's attributes. For this reason, all Eloquent models protect against mass-assignment by default.
複数代入を使用するにはfillable
かguarded
プロパティをモデルに設定してください。To get started, set the fillable
or guarded
properties on your model.
モデルの複数代入可能な属性の指定Defining Fillable Attributes On A Model
fillable
プロパティーは複数代入を許す属性を指定します。クラスとインスタンスの両レベルで設定できます。The fillable
property specifies which attributes should be mass-assignable. This can be set at the class or instance level.
class User extends Model {
protected $fillable = ['first_name', 'last_name', 'email'];
}
この例では、リストされている3属性のみ、複数代入されます。In this example, only the three listed attributes will be mass-assignable.
保護するモデル属性の指定Defining Guarded Attributes On A Model
このfillable
の反対がguarded
です。「ホワイトリスト」ではなく、「ブラックリスト」として利用します。The inverse of fillable
is guarded
, and serves as a "black-list" instead of a "white-list":
class User extends Model {
protected $guarded = ['id', 'password'];
}
注目:
guarded
を使用する場合、守られて(guarded)いないカラムが更新されてしまうため、Input::get()
や、ユーザーがコントロールできる配列をそのまま、save
やupdate
メソッドには渡すべきではありません。Note: When usingguarded
, you should still never passInput::get()
or any raw array of user controlled input into asave
orupdate
method, as any column that is not guarded may be updated.
全属性を複数代入から保護Blocking All Attributes From Mass Assignment
前の例では、id
とpassword
属性が複数代入の対象外となります。その他の属性は複数代入されます。全属性を複数代入から保護するには、guardプロパティーを使用してください。In the example above, the id
and password
attributes may not be mass assigned. All other attributes will be mass assignable. You may also block all attributes from mass assignment using the guard property:
protected $guarded = ['*'];
INSERT、UPDATE、DELETEInsert, Update, Delete
モデルから新しいレコードを作成するには、モデルの新しいインスタンスを作成し、save
メソッドを呼び出します。To create a new record in the database from a model, simply create a new model instance and call the save
method.
新しいモデルの保存Saving A New Model
$user = new User;
$user->name = 'John';
$user->save();
注目: Eloquentモデルは、新規作成時にキーを自動的に増加させるのが、典型的な使用法です。しかし、自分でキーを設定したい場合は、モデルの
incrementing
プロパティをfalse
にセットしてください。Note: Typically, your Eloquent models will have auto-incrementing keys. However, if you wish to specify your own keys, set theincrementing
property on your model tofalse
.
もしくは、一行書くだけで新しいモデルを保存するために、create
メソッドを使用することも可能です。挿入されたモデルのインスタンスが、メソッドから返されます。このメソッドを使用する場合も、全Eloquentモデルが複数代入からデフォルトで保護されているため、使用する前に操作対象のモデルに対し、fillable
かguarded
プロパティのどちらかで代入可能にする属性を指定しておく必要があります。You may also use the create
method to save a new model in a single line. The inserted model instance will be returned to you from the method. However, before doing so, you will need to specify either a fillable
or guarded
attribute on the model, as all Eloquent models protect against mass-assignment.
IDの自動増分を設定しているモデルを保存、もしくは新しく作成した後、そのIDを取得したい場合は、オブジェクトのid
属性にアクセスしてください。After saving or creating a new model that uses auto-incrementing IDs, you may retrieve the ID by accessing the object's id
attribute:
$insertedId = $user->id;
保護されたモデル属性の設定Setting The Guarded Attributes On The Model
class User extends Model {
protected $guarded = ['id', 'account_id'];
}
createメソッドの使用Using The Model Create Method
// データベースに新しいユーザーを作成する
$user = User::create(['name' => 'John']);
// 属性により、ユーザーを取得するか、存在していない場合は作成する
$user = User::firstOrCreate(['name' => 'John']);
// 属性により、ユーザーを取得するか、新しいインスタンスを生成する
$user = User::firstOrNew(['name' => 'John']);
取得したモデルの更新Updating A Retrieved Model
モデルを更新する場合は、先ず取得し、その内容を変更してから、save
メソッドを使用します。To update a model, you may retrieve it, change an attribute, and use the save
method:
$user = User::find(1);
$user->email = 'john@foo.com';
$user->save();
モデルと関連の保存Saving A Model And Relationships
そのモデルだけでなく、関連を全部まとめて保存したい場合もあるでしょう。そんな場合は、push
メソッドを使用してください。Sometimes you may wish to save not only a model, but also all of its relationships. To do so, you may use the push
method:
$user->push();
複数のモデルに対しクエリーで更新することもできます。You may also run updates as queries against a set of models:
$affectedRows = User::where('votes', '>', 100)->update(['status' => 2]);
注意: 上記のように一連のモデルをまとめてEloquentクエリービルダーで更新する場合、モデルのイベントは発行されません。Note: No model events are fired when updating a set of models via the Eloquent query builder.
既存モデルの削除Deleting An Existing Model
削除するには、インスタンスに対しdeleteメソッドを使用するだけです。To delete a model, simply call the delete
method on the instance:
$user = User::find(1);
$user->delete();
キー指定による既存モデルの削除Deleting An Existing Model By Key
User::destroy(1);
User::destroy([1, 2, 3]);
User::destroy(1, 2, 3);
もちろん、deleteクエリーで複数のモデルを削除できます。Of course, you may also run a delete query on a set of models:
$affectedRows = User::where('votes', '>', 100)->delete();
モデルのタイムスタンプだけのアップデートUpdating Only The Model's Timestamps
モデルのタイムスタンプだけをアップデートしたい場合は、touch
メソッドを使用します。If you wish to simply update the timestamps on a model, you may use the touch
method:
$user->touch();
ソフトデリートSoft Deleting
モデルをソフトデリートする場合、データーベースから実際に削除されるわけではありません。代わりにレコードへdeleted_at
タイムスタンプをセットします。モデルのソフトデリートを有効にするには、SoftDeletes
トレイトを適用してください。When soft deleting a model, it is not actually removed from your database. Instead, a deleted_at
timestamp is set on the record. To enable soft deletes for a model, apply the SoftDeletes
to the model:
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model {
use SoftDeletes;
protected $dates = ['deleted_at'];
}
deleted_at
カラムをテーブルに追加するには、マイグレーションでsoftDeletes
メソッドが使用できます。To add a deleted_at
column to your table, you may use the softDeletes
method from a migration:
$table->softDeletes();
これでモデルに対し、delete
メソッドを使用すれば、deleted_at
カラムに現在の時間がセットされます。ソフトデリートされたモデルに対しクエリーがあっても、「削除済み」のモデルはクエリー結果に含まれません。Now, when you call the delete
method on the model, the deleted_at
column will be set to the current timestamp. When querying a model that uses soft deletes, the "deleted" models will not be included in query results.
ソフトデリートされたモデルも結果に含めるように強制Forcing Soft Deleted Models Into Results
ソフトデリートされたモデルも結果に含めたい場合、withTrashed
メソッドをクエリーに使用してください。To force soft deleted models to appear in a result set, use the withTrashed
method on the query:
$users = User::withTrashed()->where('account_id', 1)->get();
定義済みの関連付けに対して、withTrashed
メソッドを使用することができます。The withTrashed
method may be used on a defined relationship:
$user->posts()->withTrashed()->get();
ソフトデリートされたモデルのみに対しクエリーしたい場合は、onlyTrashed
メソッドを使用します。If you wish to only receive soft deleted models in your results, you may use the onlyTrashed
method:
$users = User::onlyTrashed()->where('account_id', 1)->get();
ソフトデリートされたモデルを既存状態へ復活させるには、restore
メソッドを使ってください。To restore a soft deleted model into an active state, use the restore
method:
$user->restore();
restore
メソッドはクエリーと共に使用することもできます。You may also use the restore
method on a query:
User::withTrashed()->where('account_id', 1)->restore();
withTrashed
と同様に、restore
メソッドも、関連付けに対して使用することができます。Like with withTrashed
, the restore
method may also be used on relationships:
$user->posts()->restore();
モデルを本当にデータベースから削除したい場合は、forceDelete
メソッドを使用してください。If you wish to truly remove a model from the database, you may use the forceDelete
method:
$user->forceDelete();
これも関連付けに対して使用することもできます。The forceDelete
method also works on relationships:
$user->posts()->forceDelete();
指定したモデルのインスタンスがソフトデリートされたものか判断するには、trashed
メソッドを使用します。To determine if a given model instance has been soft deleted, you may use the trashed
method:
if ($user->trashed())
{
//
}
タイムスタンプTimestamps
デフォルトでEloquentはデータベースのcreated_at
(作成時間)とupdated_at
(更新時間)カラムを自動的に更新します。上記のタイムスタンプカラムをテーブルに追加するだけで、Eloquentが残りの面倒を見ます。Eloquentによる2カラムのメンテナンスがご希望でなければ、モデルに以下のプロパティを追加してください。By default, Eloquent will maintain the created_at
and updated_at
columns on your database table automatically. Simply add these timestamp
columns to your table and Eloquent will take care of the rest. If you do not wish for Eloquent to maintain these columns, add the following property to your model:
自動タイムスタンプ無効Disabling Auto Timestamps
class User extends Model {
protected $table = 'users';
public $timestamps = false;
}
タイムスタンプのカスタム形式の指定Providing A Custom Timestamp Format
タイムスタンプのフォーマットをカスタマイズしたい場合は、getDateFormat
メソッドをモデルの中でオーバーライドしてください。If you wish to customize the format of your timestamps, you may override the getDateFormat
method in your model:
class User extends Model {
protected function getDateFormat()
{
return 'U';
}
}
クエリースコープQuery Scopes
クエリースコープの定義Defining A Query Scope
スコープにより、モデルに対するクエリーロジックを簡単に再使用できるようにできます。スコープを定義するには、モデルのメソッド名の先頭にscope
を付けてください。Scopes allow you to easily re-use query logic in your models. To define a scope, simply prefix a model method with scope
:
class User extends Model {
public function scopePopular($query)
{
return $query->where('votes', '>', 100);
}
public function scopeWomen($query)
{
return $query->whereGender('W');
}
}
クエリースコープの使用Utilizing A Query Scope
$users = User::popular()->women()->orderBy('created_at')->get();
動的スコープDynamic Scopes
スコープに引数を渡したい場合もあるでしょう。スコープのメソッドに引数を追加するだけです。Sometimes you may wish to define a scope that accepts parameters. Just add your parameters to your scope function:
class User extends Model {
public function scopeOfType($query, $type)
{
return $query->whereType($type);
}
}
後はスコープの呼び出し時に、引数を指定してください。Then pass the parameter into the scope call:
$users = User::ofType('member')->get();
グローバルスコープGlobal Scopes
モデルで動かす全クエリーに対し、適用する必要があるスコープを定義することもあるでしょう。実際に、Eloquentの「ソフトデリート」機能はこれを使用しています。グローバルスコープは、PHPのトレイトとIlluminate\Database\Eloquent\ScopeInterface
の実装を組み合わせ、定義します。Sometimes you may wish to define a scope that applies to all queries performed on a model. In essence, this is how Eloquent's own "soft delete" feature works. Global scopes are defined using a combination of PHP traits and an implementation of Illuminate\Database\Eloquent\ScopeInterface
.
最初にトレイトを定義します。例として、Laravelに組み込まれているSoftDeletes
を使いましょう。First, let's define a trait. For this example, we'll use the SoftDeletes
that ships with Laravel:
trait SoftDeletes {
/**
* モデルのため、ソフトデリートトレイトを起動する
*
* @return void
*/
public static function bootSoftDeletes()
{
static::addGlobalScope(new SoftDeletingScope);
}
}
Eloquentモデルにbootトレイトの名前
という命名規則に一致するメソッドが存在するならば、グローバールスコープを登録したり、もしくは皆さんが行いたい別の操作をしたりする機会を作るため、Eloquentモデルの起動時に対象のトレイトメソッドが呼び出されます。スコープはapply
とremove
メソッドの2つを持つ、ScopeInterface
を実装しなくてはなりません。If an Eloquent model uses a trait that has a method matching the bootNameOfTrait
naming convention, that trait method will be called when the Eloquent model is booted, giving you an opportunity to register a global scope, or do anything else you want. A scope must implement ScopeInterface
, which specifies two methods: apply
and remove
.
apply
メソッドはIlluminate\Database\Eloquent\Builder
クエリービルダーオブジェクトを引数に取り、Model
は適用先です。apply
メソッドは、そのスコープで追加したいwhere
節を付け加えることに責任を持ちます。remove
メソッドもBuilder
オブジェクトとModel
を引数として受け取り、apply
で行う操作を逆転することに責任を持ちます。言い換えれば、remove
は追加したwhere
(もしくは他の節も全部)を削除する必要があります。これらを当てはめると、SoftDeletingScope
は次のようになります。The apply
method receives an Illuminate\Database\Eloquent\Builder
query builder object and the Model
it's applied to, and is responsible for adding any additional where
clauses that the scope wishes to add. The remove
method also receives a Builder
object and Model
and is responsible for reversing the action taken by apply
. In other words, remove
should remove the where
clause (or any other clause) that was added. So, for our SoftDeletingScope
, the methods look something like this:
/**
* 指定されたEloquentクエリービルダーにスコープを適用する
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->whereNull($model->getQualifiedDeletedAtColumn());
$this->extend($builder);
}
/**
* 指定されたEloquentクエリービルダーからスコープを削除する
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/
public function remove(Builder $builder, Model $model)
{
$column = $model->getQualifiedDeletedAtColumn();
$query = $builder->getQuery();
foreach ((array) $query->wheres as $key => $where)
{
// where節がソフトデリートのデータ制約によるものであれば、クエリーから削除し
// whereのキーをリセットする。これにより開発者は削除済みモデルを関連付けに
// 含めることができ、遅延ロードされた結果をセットできる。
if ($this->isSoftDeleteConstraint($where, $column))
{
unset($query->wheres[$key]);
$query->wheres = array_values($query->wheres);
}
}
}
リレーションRelationships
もちろん、皆さんのデータベーステーブルは他のテーブルと関連していることでしょう。例えば、ブログポストは多くのコメントを持つでしょうし、注文は購入したユーザーと関連しているでしょう。Eloquentはこれらの関連を簡単に操作できるように管理します。Laravelは多くの関連をサポートしています。Of course, your database tables are probably related to one another. For example, a blog post may have many comments, or an order could be related to the user who placed it. Eloquent makes managing and working with these relationships easy. Laravel supports many types of relationships:
- 1対1One To One[#one-to-one]
- 1対多One To Many[#one-to-many]
- 多対多Many To Many[#many-to-many]
- 他テーブルを経由した多対多Has Many Through[#has-many-through]
- 多様対応関係Polymorphic Relations[#polymorphic-relations]
- 多対多 多様対応関係Many To Many Polymorphic Relations[#many-to-many-polymorphic-relations]
1対1One To One
1対1関係の定義Defining A One To One Relation
1対1関係は基本です。例えば、User
モデルはPhone
モデルを一つ持つ("has one")としましょう。この関係をEloquentで定義します。A one-to-one relationship is a very basic relation. For example, a User
model might have one Phone
. We can define this relation in Eloquent:
class User extends Model {
public function phone()
{
return $this->hasOne('App\Phone');
}
}
hasOne
メソッドの最初の引数は関係するモデルの名前です。関連を定義したら、Eloquentの動的プロパティを使用し取得できます。The first argument passed to the hasOne
method is the name of the related model. Once the relationship is defined, we may retrieve it using Eloquent's dynamic properties[#dynamic-properties]:
$phone = User::find(1)->phone;
この文は以下のSQLとして動作します。The SQL performed by this statement will be as follows:
select * from users where id = 1
select * from phones where user_id = 1
Eloquentはモデル名を元に、関連の外部キーを決めることに注目してください。この例の場合、Phone
モデルはuser_id
外部キーを使用しようとします。この規約をオーバーライドしたいときは、hasOne
メソッドの第2引数を指定してください。さらに関連で使用するローカルカラムを指定するために、メソッドの第3引数を渡すこともできます。Take note that Eloquent assumes the foreign key of the relationship based on the model name. In this case, Phone
model is assumed to use a user_id
foreign key. If you wish to override this convention, you may pass a second argument to the hasOne
method. Furthermore, you may pass a third argument to the method to specify which local column that should be used for the association:
return $this->hasOne('App\Phone', 'foreign_key');
return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
逆の関連付の定義Defining The Inverse Of A Relation
Phone
モデルの関連を逆に定義するには、belongsTo
メソッドを使います。To define the inverse of the relationship on the Phone
model, we use the belongsTo
method:
class Phone extends Model {
public function user()
{
return $this->belongsTo('App\User');
}
}
上の例で、Eloquentはphones
テーブルのuser_id
カラムを探します。もし、他の外部キーを定義したい場合は、belongsTo
メソッドの第2引数に渡してください。In the example above, Eloquent will look for a user_id
column on the phones
table. If you would like to define a different foreign key column, you may pass it as the second argument to the belongsTo
method:
class Phone extends Model {
public function user()
{
return $this->belongsTo('App\User', 'local_key');
}
}
さらに、親テーブルの関連するカラム名を第3引数として指定するできます。Additionally, you pass a third parameter which specifies the name of the associated column on the parent table:
class Phone extends Model {
public function user()
{
return $this->belongsTo('App\User', 'local_key', 'parent_key');
}
}
1対多One To Many
1対多の関連の例として、「プログポストは多くのコメントを持つ(has many)」があります。このような関係をモデルに定義します。An example of a one-to-many relation is a blog post that "has many" comments. We can model this relation like so:
class Post extends Model {
public function comments()
{
return $this->hasMany('App\Comment');
}
}
これで動的プロパティを使用し、ポストのコメントへアクセスできます。Now we can access the post's comments through the dynamic property[#dynamic-properties]:
$comments = Post::find(1)->comments;
取得するコメントを制限する必要がある場合、comments
メソッドを呼び出し条件をチェーンでつなげることができます。If you need to add further constraints to which comments are retrieved, you may call the comments
method and continue chaining conditions:
$comments = Post::find(1)->comments()->where('title', '=', 'foo')->first();
ここでも、hasMany
メソッドの第2引数を指定し、外部キーの規約をオーバーライドできます。さらに、hasOne
リレーションと同様、ローカルカラムも指定できます。Again, you may override the conventional foreign key by passing a second argument to the hasMany
method. And, like the hasOne
relation, the local column may also be specified:
return $this->hasMany('App\Comment', 'foreign_key');
return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
逆の関連付の定義Defining The Inverse Of A Relation
Comment
モデルに逆の関係を定義するには、belongsTo
を使用します。To define the inverse of the relationship on the Comment
model, we use the belongsTo
method:
class Comment extends Model {
public function post()
{
return $this->belongsTo('App\Post');
}
}
多対多Many To Many
多対多の関係はもっと複雑なリレーションタイプです。このような関係として、ユーザ(user)が多くの役目(roles)を持ち、役目(role)も大勢のユーザー(users)に共有されるという例が挙げられます。例えば、多くのユーザーは"管理者"の役目を持っているとしましょう。users
、roles
、role_user
の3テーブルがこの関係には必要です。role_user
テーブルは関係するモデル名をアルファベット順に並べたもので、user_id
とrole_id
を持つ必要があります。Many-to-many relations are a more complicated relationship type. An example of such a relationship is a user with many roles, where the roles are also shared by other users. For example, many users may have the role of "Admin". Three database tables are needed for this relationship: users
, roles
, and role_user
. The role_user
table is derived from the alphabetical order of the related model names, and should have user_id
and role_id
columns.
多対多の関係はbelongsToMany
メソッドで定義します。We can define a many-to-many relation using the belongsToMany
method:
class User extends Model {
public function roles()
{
return $this->belongsToMany('App\Role');
}
}
では、User
モデルを通して、役割を取得しましょう。Now, we can retrieve the roles through the User
model:
$roles = User::find(1)->roles;
もしピボットテーブル名に規約から外れた名前を使用したい場合は、belongsToMany
メソッドの第2引数に渡してください。If you would like to use an unconventional table name for your pivot table, you may pass it as the second argument to the belongsToMany
method:
return $this->belongsToMany('App\Role', 'user_roles');
更に関係するキー名の規約をオーバーライドするには:You may also override the conventional associated keys:
return $this->belongsToMany('App\Role', 'user_roles', 'user_id', 'foo_id');
もちろん、Role
モデルに対し逆のリレーションを定義することもできます。Of course, you may also define the inverse of the relationship on the Role
model:
class Role extends Model {
public function users()
{
return $this->belongsToMany('App\User');
}
}
他テーブルを経由した多対多Has Many Through
「〜経由の多対多(has many through)」リレーションは、仲介するテーブルを通して、直接関連付けしていないテーブルへアクセスするための、便利な近道を提供します。例えば、Country
モデルはUsers
モデルを経由して、多くのPosts
を所有することでしょう。テーブルは以下のような構成になります。The "has many through" relation provides a convenient short-cut for accessing distant relations via an intermediate relation. For example, a Country
model might have many Post
through a User
model. The tables for this relationship would look like this:
countries
id - integer
name - string
users
id - integer
country_id - integer
name - string
posts
id - integer
user_id - integer
title - string
例えposts
テーブルにcountry_id
が存在しなくても、hasManyThrough
リレーションでは、CountryのPostへ、$country->posts
によりアクセスできます。関連を定義付けましょう。Even though the posts
table does not contain a country_id
column, the hasManyThrough
relation will allow us to access a country's posts via $country->posts
. Let's define the relationship:
class Country extends Model {
public function posts()
{
return $this->hasManyThrough('App\Post', 'App\User');
}
}
関連付けのキーを手動で指定したい場合、メソッドの第3引数と、第4引数として渡して下さい。If you would like to manually specify the keys of the relationship, you may pass them as the third and fourth arguments to the method:
class Country extends Model {
public function posts()
{
return $this->hasManyThrough('App\Post', 'App\User', 'country_id', 'user_id');
}
}
多様対応関係Polymorphic Relations
多様対応(polymorphic:ポリモーフィック)関係は、あるモデルを一つの関係だけで、複数のモデルに所属させるものです。例えば写真モデルがあり、スタッフモデルと注文モデルの両方に所属しているとしましょう。この関係を次のように定義できます。Polymorphic relations allow a model to belong to more than one other model, on a single association. For example, you might have a photo model that belongs to either a staff model or an order model. We would define this relation like so:
class Photo extends Model {
public function imageable()
{
return $this->morphTo();
}
}
class Staff extends Model {
public function photos()
{
return $this->morphMany('App\Photo', 'imageable');
}
}
class Order extends Model {
public function photos()
{
return $this->morphMany('App\Photo', 'imageable');
}
}
多様対応関係で取得するRetrieving A Polymorphic Relation
では、スタッフと注文を通して、写真を取得してみましょう。Now, we can retrieve the photos for either a staff member or an order:
$staff = Staff::find(1);
foreach ($staff->photos as $photo)
{
//
}
多様対応関連の所有者を取得するRetrieving The Owner Of A Polymorphic Relation
しかし、本当の「多様対応関係」マジックは、スタッフと注文を写真('Photo')モデルを通じてアクセスする場合に現れます。However, the true "polymorphic" magic is when you access the staff or order from the Photo
model:
$photo = Photo::find(1);
$imageable = $photo->imageable;
Photo
モデルのimageable
関係は写真を所有しているモデルのタイプにより、Staff
もしくはOrder
どちらかのインスタンスをリターンします。The imageable
relation on the Photo
model will return either a Staff
or Order
instance, depending on which type of model owns the photo.
多様対応関係のテーブル構造Polymorphic Relation Table Structure
これがどの様に動作するのか理解を助けるために、多様対応関係のデータベース構造を説明しましょう。To help understand how this works, let's explore the database structure for a polymorphic relation:
staff
id - integer
name - string
orders
id - integer
price - integer
photos
id - integer
path - string
imageable_id - integer
imageable_type - string
注目すべき鍵となるフィールドは、photos
テーブルのimageable_id
とimageable_type
です。この例の場合、IDは所有しているスタッフか注文のIDで、タイプは所有しているモデルのクラス名です。これにより、ORMが所有しているモデルのタイプを決定し、imageable
関係でアクセスした時にそのモデルをリターンする仕組みです。The key fields to notice here are the imageable_id
and imageable_type
on the photos
table. The ID will contain the ID value of, in this example, the owning staff or order, while the type will contain the class name of the owning model. This is what allows the ORM to determine which type of owning model to return when accessing the imageable
relation.
多対多−多様対応関係Many To Many Polymorphic Relations
多対多−多様対応関係のテーブル構造Polymorphic Many To Many Relation Table Structure
伝統的な多様対応関係に加え、多対多-多様対応関係も指定することができます。例えば、ブログのPost
とVideo
モデルは、Tag
モデルに対する多様対応関係を共有できます。最初に、テーブル構造を確認しましょう。In addition to traditional polymorphic relations, you may also specify many-to-many polymorphic relations. For example, a blog Post
and Video
model could share a polymorphic relation to a Tag
model. First, let's examine the table structure:
posts
id - integer
name - string
videos
id - integer
name - string
tags
id - integer
name - string
taggables
tag_id - integer
taggable_id - integer
taggable_type - string
次に、モデルにその関係を用意しましょう。Post
とVideo
モデルは、tags
メソッドを通じ、両方共にmorphToMany
関係を持ちます。Next, we're ready to setup the relationships on the model. The Post
and Video
model will both have a morphToMany
relationship via a tags
method:
class Post extends Model {
public function tags()
{
return $this->morphToMany('App\Tag', 'taggable');
}
}
Tag
モデルでは、それぞれの関係を表すメソッドを定義します。The Tag
model may define a method for each of its relationships:
class Tag extends Model {
public function posts()
{
return $this->morphedByMany('App\Post', 'taggable');
}
public function videos()
{
return $this->morphedByMany('App\Video', 'taggable');
}
}
リレーションの問い合わせQuerying Relations
SELECT時にリレーションを問い合わせるQuerying Relations When Selecting
関連付けたモデルのレコードに基づいて、モデルのレコードに対するマッチングを絞り込みたい場合もあるでしょう。例えば、最低でも一つのコメントを持つ、全ブログポストを取得したい場合です。これを行うためにはhas
メソッドを使用します。When accessing the records for a model, you may wish to limit your results based on the existence of a relationship. For example, you wish to pull all blog posts that have at least one comment. To do so, you may use the has
method:
$posts = Post::has('comments')->get();
演算子とレコード数も指定できます。You may also specify an operator and a count:
$posts = Post::has('comments', '>=', 3)->get();
ネストしたhas
文は、「ドット」記法で組立てられます。Nested has
statements may also be constructed using "dot" notation:
$posts = Post::has('comments.votes')->get();
もっと強力な機能がお望みならば、has
の問い合わせに、"where"で条件をつけるために、whereHas
やorWhereHas
を利用して下さい。If you need even more power, you may use the whereHas
and orWhereHas
methods to put "where" conditions on your has
queries:
$posts = Post::whereHas('comments', function($q)
{
$q->where('content', 'like', 'foo%');
})->get();
動的プロパティDynamic Properties
Eloquentは動的プロパティーを使用し、関係にアクセスする方法を提供しています。Eloquentは自動的にその関係をロードし、賢いことにget
(1対多関係)メソッドとfirst
(1対1関係)メソッドを使い分けます。動的プロパティーでアクセスするにはその関係名をメソッド名として使います。例えば、次のPhone
モデルをご覧ください。Eloquent allows you to access your relations via dynamic properties. Eloquent will automatically load the relationship for you, and is even smart enough to know whether to call the get
(for one-to-many relationships) or first
(for one-to-one relationships) method. It will then be accessible via a dynamic property by the same name as the relation. For example, with the following model $phone
:
class Phone extends Model {
public function user()
{
return $this->belongsTo('App\User');
}
}
$phone = Phone::find(1);
通常、以下のようにメールアドレスをechoします。Instead of echoing the user's email like this:
echo $phone->user()->first()->email;
その代わりに、もっとシンプルで短く記述できます。It may be shortened to simply:
echo $phone->user->email;
複数の結果をリターンするリレーションは、
Illuminate\Database\Eloquent\Collection
クラスのインスタンスを返します。Note: Relationships that return many results will return an instance of theIlluminate\Database\Eloquent\Collection
class.
EagerローディングEager Loading
EagerローディングはN+1クエリー問題を軽減するために用意しています。例えば、Book
モデルがAuthor
モデルと関連していると考えてください。関係はこのように定義されます。Eager loading exists to alleviate the N + 1 query problem. For example, consider a Book
model that is related to Author
. The relationship is defined like so:
class Book extends Model {
public function author()
{
return $this->belongsTo('App\Author');
}
}
では、次のコードを考察してみましょう。Now, consider the following code:
foreach (Book::all() as $book)
{
echo $book->author->name;
}
このループでは、まず全ての本をテーブルから取得するために1クエリー実行され、それから著者をそれぞれの本について取得します。ですから、25冊あるならば、このループで26クエリーが発生します。This loop will execute 1 query to retrieve all of the books on the table, then another query for each book to retrieve the author. So, if we have 25 books, this loop would run 26 queries.
ありがたいことに、クエリーの数を徹底的に減らすためにEager(イーガー:熱心な)ローディングを使うことができます。with
メソッドを使い、指定してください。Thankfully, we can use eager loading to drastically reduce the number of queries. The relationships that should be eager loaded may be specified via the with
method:
foreach (Book::with('author')->get() as $book)
{
echo $book->author->name;
}
上のループでは、2つだけしかクエリーが実行されません。In the loop above, only two queries will be executed:
select * from books
select * from authors where id in (1, 2, 3, 4, 5, ...)
賢くEagerローディングを使用することで、アプリケーションのパフォーマンスを大幅に向上させることができます。Wise use of eager loading can drastically increase the performance of your application.
もちろん、一度に複数の関係をEagerローディングすることもできます。Of course, you may eager load multiple relationships at one time:
$books = Book::with('author', 'publisher')->get();
ネストした関連でさえ、Eagerローディングできます。You may even eager load nested relationships:
$books = Book::with('author.contacts')->get();
上記では、author
関係がEagerローディングされ、それからauthorのcontacts
関係がEagerローディングされます。In the example above, the author
relationship will be eager loaded, and the author's contacts
relation will also be loaded.
Eagerローディングの条件付けEager Load Constraints
関係をEagerローディングする時に、条件を付けたい場合もあります。一例をご覧ください。Sometimes you may wish to eager load a relationship, but also specify a condition for the eager load. Here's an example:
$users = User::with(['posts' => function($query)
{
$query->where('title', 'like', '%first%');
}])->get();
この例では、ユーザーの写真をEagerローディングしていますが、写真のタイトルが"first"という単語で構成されているものだけが取得されます。In this example, we're eager loading the user's posts, but only if the post's title column contains the word "first".
もちろん、Eagerローディングクロージャーは、「検索条件」指定だけに限定されていません。ソート順も指定できます。Of course, eager loading Closures aren't limited to "constraints". You may also apply orders:
$users = User::with(['posts' => function($query)
{
$query->orderBy('created_at', 'desc');
}])->get();
遅延EagerローディングLazy Eager Loading
既に存在しているモデルコレクションから直接関係をEagerローディングすることも可能です。これは関係するモデルをロードするかどうかを動的に決める場合や、キャッシュと結びつける場合に便利です。It is also possible to eagerly load related models directly from an already existing model collection. This may be useful when dynamically deciding whether to load related models or not, or in combination with caching.
$books = Book::all();
$books->load('author', 'publisher');
クロージャーでクエリーに制約を設定することもできます。You may also pass a Closure to set constraints on the query:
$books->load(['author' => function($query)
{
$query->orderBy('published_date', 'asc');
}]);
関連したモデルの挿入Inserting Related Models
関連するモデルを追加するAttaching A Related Model
関連するモデルを新しく挿入する機会も多いと思います。例えば、ポストに対して新しいコメントを挿入する場合です。モデルに外部キーとしてpost_id
をセットする代わりに、新しいコメントを親のPost
モデルから直接挿入できます。You will often need to insert new related models. For example, you may wish to insert a new comment for a post. Instead of manually setting the post_id
foreign key on the model, you may insert the new comment from its parent Post
model directly:
$comment = new Comment(['message' => 'A new comment.']);
$post = Post::find(1);
$comment = $post->comments()->save($comment);
この例では、post_id
フィールドは自動的にセットされ、コメントが挿入されます。In this example, the post_id
field will automatically be set on the inserted comment.
関連するモデルを一度に追加することもできます。If you need to save multiple related models:
$comments = [
new Comment(['message' => 'A new comment.']),
new Comment(['message' => 'Another comment.']),
new Comment(['message' => 'The latest comment.'])
];
$post = Post::find(1);
$post->comments()->saveMany($comments);
関係づけられているモデル(所属)Associating Models (Belongs To)
belongsTo
関係を更新する場合、associate
メソッドを使用できます。このメソッドは子供のモデルに外部キーをセットします。When updating a belongsTo
relationship, you may use the associate
method. This method will set the foreign key on the child model:
$account = Account::find(10);
$user->account()->associate($account);
$user->save();
関連したモデルの挿入 (多対多)Inserting Related Models (Many To Many)
多対多の関連を操作する場合も、関連するモデルを挿入したい場合があるでしょう。User
とRole
の例を使い、続けて説明します。attach
メソッドを使用し、新しい役目をユーザーに追加することができます。You may also insert related models when working with many-to-many relations. Let's continue using our User
and Role
models as examples. We can easily attach new roles to a user using the attach
method:
多対多モデルを追加するAttaching Many To Many Models
$user = User::find(1);
$user->roles()->attach(1);
その関係に対してピボットテーブルに保存する属性の配列を渡すこともできます。You may also pass an array of attributes that should be stored on the pivot table for the relation:
$user->roles()->attach(1, ['expires' => $expires]);
もちろんattach
の反対はdetach
です。Of course, the opposite of attach
is detach
:
$user->roles()->detach(1);
attach
とdetach
の両方共に、IDの配列を指定することができます。Both attach
and detach
also take arrays of IDs as input:
$user = User::find(1);
$user->roles()->detach([1, 2, 3]);
$user->roles()->attach([1 => ['attribute1' => 'value1'], 2, 3]);
多対多モデルの追加にSyncを使用するUsing Sync To Attach Many To Many Models
さらにsync
メソッドで関連するモデルを追加することもできます。sync
メソッドはピボットテーブルに設置するIDの配列を渡します。これによる操作が終了すると、そのモデルに対する中間テーブルは配列で指定されたIDだけになります。You may also use the sync
method to attach related models. The sync
method accepts an array of IDs to place on the pivot table. After this operation is complete, only the IDs in the array will be on the intermediate table for the model:
$user->roles()->sync([1, 2, 3]);
Syncを使い、ピボットデーターを追加するAdding Pivot Data When Syncing
IDを指定して他のピボットテーブル値を関連付けることもできます。You may also associate other pivot table values with the given IDs:
$user->roles()->sync([1 => ['expires' => true]]);
時にはひとつのコマンドで、関連するモデルを作成し、追加したいこともあるでしょう。その場合、save
メソッドを使用してください。Sometimes you may wish to create a new related model and attach it in a single command. For this operation, you may use the save
method:
$role = new Role(['name' => 'Editor']);
User::find(1)->roles()->save($role);
この例では、新しいRole
モデルは保存され、ユーザーモデルに結び付けられます。更に以下の操作で、関連するテーブルに設定する属性の配列を渡すことができます。In this example, the new Role
model will be saved and attached to the user model. You may also pass an array of attributes to place on the joining table for this operation:
User::find(1)->roles()->save($role, ['expires' => $expires]);
親のタイムスタンプの更新Touching Parent Timestamps
例えばComment
がPost
に所属しているような場合、子供のモデルが変更された場合、所属している(belongsTo)親のタイムスタンプも変更されると便利です。Comment
モデルが更新されたら、Post
が持っているupdated_at
タイムスタンプも自動的に更新したい場合などです。Eloquentでは簡単に実現できます。子供のモデルでtouches
プロパティーに、関連名を付け加えてください。When a model belongsTo
another model, such as a Comment
which belongs to a Post
, it is often helpful to update the parent's timestamp when the child model is updated. For example, when a Comment
model is updated, you may want to automatically touch the updated_at
timestamp of the owning Post
. Eloquent makes it easy. Just add a touches
property containing the names of the relationships to the child model:
class Comment extends Model {
protected $touches = ['post'];
public function post()
{
return $this->belongsTo('App\Post');
}
}
これで、Post
に所有されているComment
が更新されると、Post
のupdated_at
カラムも更新されるようになります。Now, when you update a Comment
, the owning Post
will have its updated_at
column updated:
$comment = Comment::find(1);
$comment->text = 'このコメントを変更!';
$comment->save();
ピボットテーブルの操作Working With Pivot Tables
既に学んだように、多対多の関連を操作するためには中間テーブルが必要です。Eloquentはこのテーブルを操作するために役に立つ手法も提供しています。例えば、User
オブジェクトが多くの関連するRole
オブジェクトを所有しているとしましょう。この関連にアクセスした後に、モデルに対するピボット(pivot
)テーブルにもアクセスできます。As you have already learned, working with many-to-many relations requires the presence of an intermediate table. Eloquent provides some very helpful ways of interacting with this table. For example, let's assume our User
object has many Role
objects that it is related to. After accessing this relationship, we may access the pivot
table on the models:
$user = User::find(1);
foreach ($user->roles as $role)
{
echo $role->pivot->created_at;
}
取得されたRole
モデルそれぞれは、自動的にpivot
属性を与えられていることに注目してください。この属性は中間テーブルを表すモデルで、他のEloquentモデルと同様に使用できます。Notice that each Role
model we retrieve is automatically assigned a pivot
attribute. This attribute contains a model representing the intermediate table, and may be used as any other Eloquent model.
デフォルトでは、pivot
オブジェクトにはキーしかありません。もし、あなたのピボットテーブルにその他の属性があるのでしたら、関連を定義する時にそれを指定する必要があります。By default, only the keys will be present on the pivot
object. If your pivot table contains extra attributes, you must specify them when defining the relationship:
return $this->belongsToMany('App\Role')->withPivot('foo', 'bar');
これでRole
モデルのpivot
オブジェクトで、foo
とbar
属性がアクセス可能になります。Now the foo
and bar
attributes will be accessible on our pivot
object for the Role
model.
もしピボットテーブルでも自動的にcreated_at
とupdated_at
タイムスタンプを更新したい場合は、関係の定義にwithTimestamps
メソッドを使用してください。If you want your pivot table to have automatically maintained created_at
and updated_at
timestamps, use the withTimestamps
method on the relationship definition:
return $this->belongsToMany('App\Role')->withTimestamps();
Pivotテーブルのレコード削除Deleting Records On A Pivot Table
モデルのピボットテーブルの全レコードを削除したい場合は、detach
メソッドを使用してください。To delete all records on the pivot table for a model, you may use the detach
method:
User::find(1)->roles()->detach();
この操作はroles
テーブルからレコードを削除せず、ピボットテーブルに対してだけ操作されることに注目してください。Note that this operation does not delete records from the roles
table, but only from the pivot table.
ピボットテーブル上のレコード更新Updating A Record On A Pivot Table
場合により、ピボットテーブルを削除せずに、更新する必要があることもあるでしょう。存在するピボットテーブルを更新したい場合は、updateExistingPivot
メソッドが使用できます。Sometimes you may need to update your pivot table, but not detach it. If you wish to update your pivot table in place you may use updateExistingPivot
method like so:
User::find(1)->roles()->updateExistingPivot($roleId, $attributes);
カスタムピボットモデルの定義Defining A Custom Pivot Model
Laravelではカスタムピボットモデルを定義することさえできます。カスタムモデルを定義するためには、最初にEloquent
を拡張したBase
モデルクラスを作成します。そして他のEloquentモデルでは、デフォルトのEloquent
の代わりに、このカスタムベースモデルを拡張しましょう。ベースモデルの中に、カスタムピボットモデルのインスタンスを返す、次のような関数を追加してください。Laravel also allows you to define a custom Pivot model. To define a custom model, first create your own "Base" model class that extends Eloquent
. In your other Eloquent models, extend this custom base model instead of the default Eloquent
base. In your base model, add the following function that returns an instance of your custom Pivot model:
public function newPivot(Model $parent, array $attributes, $table, $exists)
{
return new YourCustomPivot($parent, $attributes, $table, $exists);
}
コレクションCollections
get
メソッドであれ、関連によるものであれ、Eloquentが複数のレコードをリターンする場合、Eloquent Collection
オブジェクトが返されます。このオブジェクトはIteratorAggregate
PHPインターフェイスの実装で、そのため配列のように操作できます。更に、結果を操作するためのバラエティーに富んだ他のパワフルなメソッドも持っています。All multi-result sets returned by Eloquent, either via the get
method or a relationship
, will return a collection object. This object implements the IteratorAggregate
PHP interface so it can be iterated over like an array. However, this object also has a variety of other helpful methods for working with result sets.
特定のキーをコレクションに含んでいるか調べる。Checking If A Collection Contains A Key
例えば、contains
メソッドを使用し、指定した主キーを結果に含んでいるか調べることができます。For example, we may determine if a result set contains a given primary key using the contains
method:
$roles = User::find(1)->roles;
if ($roles->contains(2))
{
//
}
コレクションは配列やJSONに変換することもできます。Collections may also be converted to an array or JSON:
$roles = User::find(1)->roles->toArray();
$roles = User::find(1)->roles->toJson();
コレクションを文字列にキャストすると、JSONがリターンされます。If a collection is cast to a string, it will be returned as JSON:
$roles = (string) User::find(1)->roles;
コレクションの反復処理Iterating Collections
Eloquentコレクションは、中に含んでいるアイテムをループしたり、フィルタリングしたりする便利なメソッドも持っています。Eloquent collections also contain a few helpful methods for looping and filtering the items they contain:
$roles = $user->roles->each(function($role)
{
//
});
コレクションのフィルタリングFiltering Collections
コレクションをフィルタリングする場合、指定されたコールバックは、array_filterのコールバックとして利用されます。When filtering collections, the callback provided will be used as callback for array_filter[http://php.net/manual/en/function.array-filter.php].
$users = $users->filter(function($user)
{
return $user->isAdmin();
});
**注目:**コレクションをフィルタリングするか、JSONに変換する場合、
values
メソッドを最初に呼び出し、配列のキーをリセットしてください。Note: When filtering a collection and converting it to JSON, try calling thevalues
function first to reset the array's keys.
コレクションの各オブジェクトにコールバックを適用Applying A Callback To Each Collection Object
$roles = User::find(1)->roles;
$roles->each(function($role)
{
//
});
値でコレクションのソートSorting A Collection By A Value
$roles = $roles->sortBy(function($role)
{
return $role->created_at;
});
$roles = $roles->sortByDesc(function($role)
{
return $role->created_at;
});
値でコレクションのソートSorting A Collection By A Value
$roles = $roles->sortBy('created_at');
$roles = $roles->sortByDesc('created_at');
カスタムコレクションタイプの返却Returning A Custom Collection Type
カスタムメソッドをつけた、カスタムコレクションオブジェクトをリターンしたい場合もあるでしょう。EloquentモデルのnewCollection
メソッドをオーバーライドしてください。Sometimes, you may wish to return a custom Collection object with your own added methods. You may specify this on your Eloquent model by overriding the newCollection
method:
class User extends Model {
public function newCollection(array $models = [])
{
return new CustomCollection($models);
}
}
アクセサーとミューテーターAccessors & Mutators
アクセサーの定義Defining An Accessor
Eloquentはモデルの属性を設定したり取得したりする時に、内容を変更できる便利な方法を提供しています。モデルのアクセサーを宣言するには、getFooAttribute
メソッドを定義するだけです。データベースのカラムがスネークケースであったとしても、メソッドはキャメルケースにしなくてはならないことに注意してください。Eloquent provides a convenient way to transform your model attributes when getting or setting them. Simply define a getFooAttribute
method on your model to declare an accessor. Keep in mind that the methods should follow camel-casing, even though your database columns are snake-case:
class User extends Model {
public function getFirstNameAttribute($value)
{
return ucfirst($value);
}
}
上記の例は、first_name
カラムのアクセサーです。アクセサーに属性の値を渡していることに注目してください。In the example above, the first_name
column has an accessor. Note that the value of the attribute is passed to the accessor.
ミューテーターの定義Defining A Mutator
ミューテーターも同じやり方で定義します。Mutators are declared in a similar fashion:
class User extends Model {
public function setFirstNameAttribute($value)
{
$this->attributes['first_name'] = strtolower($value);
}
}
日付ミューテーターDate Mutators
デフォルトでEloquentはcreated_at、updated_atカラムを Carbonのインスタンスに変換します。Carbonは便利なメソッドが揃っており、PHPネイティブのDateTime
クラスを拡張しています。By default, Eloquent will convert the created_at
and updated_at
columns to instances of Carbon[https://github.com/briannesbitt/Carbon], which provides an assortment of helpful methods, and extends the native PHP DateTime
class.
これらのフィールドの自動変換をカスタマイズ、またはこの変換を完全に無効にすることも、モデルのgetDates
メソッドをオーバーライドすることで可能です。You may customize which fields are automatically mutated, and even completely disable this mutation, by overriding the getDates
method of the model:
public function getDates()
{
return ['created_at'];
}
日付項目にはUNIXタイムスタンプ、日付文字列(Y-m-d
)、日付時間文字列、そしてもちろんDateTime
やCarbon
のインスタンスを設定することができます。When a column is considered a date, you may set its value to a UNIX timestamp, date string (Y-m-d
), date-time string, and of course a DateTime
/ Carbon
instance.
日付ミューテーターを完全に無効にしたい場合は、getDates
メソッドから空配列をリターンしてください。To totally disable date mutations, simply return an empty array from the getDates
method:
public function getDates()
{
return [];
}
属性の型変換Attribute Casting
常に他のデータ型へ型変換したい属性がある場合、モデルのcasts
プロパティーへ属性を追加してください。もしくは、手間がかかりますが各属性をミューテターでそれぞれ定義してください。casts
プロパティの使用例をご覧ください。If you have some attributes that you want to always convert to another data-type, you may add the attribute to the casts
property of your model. Otherwise, you will have to define a mutator for each of the attributes, which can be time consuming. Here is an example of using the casts
property:
/**
* ネイティブなタイプへ型変換しなくてはならない属性
*
* @var array
*/
protected $casts = [
'is_admin' => 'boolean',
];
これで、データベース上では整数として値が保存されていても、is_admin
属性にアクセスすれば、いつも論理型へ型変換されます。サポートしている変換型は、integer
、real
、float
、double
、string
、boolean
、object
、array
です。Now the is_admin
attribute will always be cast to a boolean when you access it, even if the underlying value is stored in the database as an integer. Other supported cast types are: integer
, real
, float
, double
, string
, boolean
, object
and array
.
array
型変換はシリアライズ済みのJSONとして保存されているカラムに利用すると特に便利です。例えば、データベースにシリアライズされたJSONがTEXTタイプのフィールドにある時、array
型変換を指定しておけば、そのEloquentモデルへアクセすると、属性がPHP配列へ自動的に非シリアライズされます。The array
cast is particularly useful for working with columns that are stored as serialized JSON. For example, if your database has a TEXT type field that contains serialized JSON, adding the array
cast to that attribute will automatically deserialize the attribute to a PHP array when you access it on your Eloquent model:
/**
* ネイティブなタイプへ型変換しなくてはならない属性
*
* @var array
*/
protected $casts = [
'options' => 'array',
];
これで、Eloquentモデルを使用します。Now, when you utilize the Eloquent model:
$user = User::find(1);
// $optionsは配列…
$options = $user->options;
// optionsは自動的にJSONに戻される…
$user->options = ['foo' => 'bar'];
モデルイベントModel Events
Eloquentモデルは多くのイベントを発行します。以降のメソッドを利用し、モデルのライフサイクルの様々な時点をフックすることができます:creating
、created
、updating
、updated
、saving
、saved
、deleting
、deleted
、restoring
、restored
Eloquent models fire several events, allowing you to hook into various points in the model's lifecycle using the following methods: creating
, created
, updating
, updated
, saving
, saved
, deleting
, deleted
, restoring
, restored
.
いつでも新しいアイテムが最初に保存される場合に、creating
とcreated
イベントが発行されます。新しくないアイテムにsave
メソッドが呼び出されると、updating
とupdated
イベントが発行されます。どちらの場合にも、saving
とsaved
イベントは発行されます。Whenever a new item is saved for the first time, the creating
and created
events will fire. If an item is not new and the save
method is called, the updating
/ updated
events will fire. In both cases, the saving
/ saved
events will fire.
イベントにより保存操作をキャンセルするCancelling Save Operations Via Events
もし、creating
、updating
、saving
、deleting
イベントでfalse
がリターンされると、そのアクションはキャンセルされます。If false
is returned from the creating
, updating
, saving
, or deleting
events, the action will be cancelled:
User::creating(function($user)
{
if ( ! $user->isValid()) return false;
});
イベントリスナーを登録する場所Where To Register Event Listeners
EventServiceProvider
はモデルのイベント結合を登録するため、便利に使えます。例をご覧ください。Your EventServiceProvider
serves as a convenient place to register your model event bindings. For example:
/**
* アプリケーションの他のイベントを登録する
*
* @param \Illuminate\Contracts\Events\Dispatcher $events
* @return void
*/
public function boot(DispatcherContract $events)
{
parent::boot($events);
User::creating(function($user)
{
//
});
}
モデルオブザーバーModel Observers
モデルのイベントを取りまとめるにはモデルオブザーバーを登録してください。オブザーバークラスは対応するそれぞれのモデルイベントのメソッドを用意します。例えば、監視するのがcreating
、updating
、saving
イベントなら、その名前のメソッドを用意します。もちろん他のモデルイベント名も追加できます。To consolidate the handling of model events, you may register a model observer. An observer class may have methods that correspond to the various model events. For example, creating
, updating
, saving
methods may be on an observer, in addition to any other model event name.
ですから、モデルオブザーバーは次のような形式になります。So, for example, a model observer might look like this:
class UserObserver {
public function saving($model)
{
//
}
public function saved($model)
{
//
}
}
オブザーバーのインスタンスはobserve
メソッドを使い、モデルへ登録してください。You may register an observer instance using the observe
method:
User::observe(new UserObserver);
モデルURL生成Model URL Generation
route
かaction
メソッドへモデルを渡すと、生成されるURIに主キーの値が挿入されます。例で確認してください。When you pass a model to the route
or action
methods, it's primary key is inserted into the generated URI. For example:
Route::get('user/{user}', 'UserController@show');
action('UserController@show', [$user]);
この場合、$user->id
プロパティが、生成されるURLの{user}
プレースフォルダー部分へ挿入されます。しかし、他のプロパティーをIDとして挿入したければ、モデルのgetRouteKey
メソッドをオーバーライドしてください。In this example the $user->id
property will be inserted into the {user}
place-holder of the generated URL. However, if you would like to use another property instead of the ID, you may override the getRouteKey
method on your model:
public function getRouteKey()
{
return $this->slug;
}
配列とJSONへの変換Converting To Arrays / JSON
モデルを配列に変換Converting A Model To An Array
JSONでAPIを作成する場合、モデルと関連をしばしば配列やJSONに変換する必要が起きます。そのため、Eloquentはこれを行うメソッドを含んでいます。モデルとそれにロードされている関連を配列に変換するには、toArray
メソッドが使用できます。When building JSON APIs, you may often need to convert your models and relationships to arrays or JSON. So, Eloquent includes methods for doing so. To convert a model and its loaded relationship to an array, you may use the toArray
method:
$user = User::with('roles')->first();
return $user->toArray();
モデルの全コレクションを配列に変換することさえできることに注目してください。Note that entire collections of models may also be converted to arrays:
return User::all()->toArray();
モデルをJSONに変換Converting A Model To JSON
モデルをJSONに変換するには、toJson
メソッドを使用します。To convert a model to JSON, you may use the toJson
method:
return User::find(1)->toJson();
ルーティングからの返却Returning A Model From A Route
モデルやコレクションを文字列に変換する場合、JSON形式に変換されることに注目してください。これが意味するのはEloquentオブジェクトを直接アプリケーションのルートからリターンできるということです!Note that when a model or collection is cast to a string, it will be converted to JSON, meaning you can return Eloquent objects directly from your application's routes!
Route::get('users', function()
{
return User::all();
});
配列とJSONへの変換から特定の属性を除くHiding Attributes From Array Or JSON Conversion
パスワードのように、モデルの配列やJSON形式に含める属性を制限したい属性もあります。そのためにはhidden
プロパティーをモデルで定義してください。Sometimes you may wish to limit the attributes that are included in your model's array or JSON form, such as passwords. To do so, add a hidden
property definition to your model:
class User extends Model {
protected $hidden = ['password'];
}
注意: リレーションを隠す場合、動的なアクセサー名を使用せずに、リレーションのメソッド名を使用してください。Note: When hiding relationships, use the relationship's method name, not the dynamic accessor name.
反対に、visible
プロパティでホワイトリストを定義することもできます。Alternatively, you may use the visible
property to define a white-list:
protected $visible = ['first_name', 'last_name'];
時にはデーターベースのカラムに対応していない属性を追加する必要もあるでしょう。これを行うには、先ず値を返すアクセサーを定義してください。
public function getIsAdminAttribute()
{
return $this->attributes['admin'] == 'yes';
}
アクセサーを作成したら、モデルのappends
プロパティーにその値を追加してください。Once you have created the accessor, just add the value to the appends
property on the model:
protected $appends = ['is_admin'];
属性をappends
リストに追加すると、モデルの配列とJSON形式の両方へ含まれるようになります。appends
配列の属性は、モデル中のvisible
とhidden
設定の影響を受けます。Once the attribute has been added to the appends
list, it will be included in both the model's array and JSON forms. Attributes in the appends
array respect the visible
and hidden
configuration on the model.