イントロダクション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
ファイルでオートロードするように指定した場所であれば、どこでも自由に設置できます。。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.
Eloquentモデルを定義するDefining An Eloquent Model
class User extends Eloquent {}
また、make:model
コマンドを使用し、Eloquentモデルを生成することもできます。You may also generate Eloquent models using the make:model
command:
php artisan make:model Photo
User
モデルにどのテーブルを使用するのかをEloquentに指定していないことに注意してください。クラス名を小文字の複数形にしたものが、テーブル名として使用されます。他の名前を使用したい場合はそれを指定します。ですからこの場合、EloquentはUser
モデルをusers
テーブルに保存します。モデルのtable
プロパティを定義し、テーブルを指定することもできます。Note that we did not tell Eloquent which table to use for our User
model. The lower-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 Eloquent {
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 Models
$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
モデルが見つからない場合、例外を投げたいこともあることでしょう。例外はApp::error
ハンドラーを使用して捕捉し、404ページを表示することが可能です。Sometimes you may wish to throw an exception if a model is not found, allowing you to catch the exceptions using an App::error
handler and display a 404 page.
$model = User::findOrFail(1);
$model = User::where('votes', '>', 100)->firstOrFail();
エラーハンドラーを登録するには、ModelNotFoundException
をリッスンしてください。To register the error handler, listen for the ModelNotFoundException
use Illuminate\Database\Eloquent\ModelNotFoundException;
App::error(function(ModelNotFoundException $e)
{
return Response::make('Not Found', 404);
});
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', array(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/master/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 Eloquent {
protected $fillable = array('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 Eloquent {
protected $guarded = array('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 = array('*');
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 Eloquent {
protected $guarded = array('id', 'account_id');
}
モデルのcreateメソッドを使用するUsing The Model Create Method
// データベースに新しいユーザーを作成する
$user = User::create(array('name' => 'John'));
// 属性により、ユーザーを取得するか、存在していない場合は作成する
$user = User::firstOrCreate(array('name' => 'John'));
// 属性により、ユーザーを取得するか、新しいインスタンスを生成する
$user = User::firstOrNew(array('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(array('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(array(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 Eloquent {
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 Eloquent {
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 Eloquent {
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 Eloquent {
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 Eloquent {
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トレイトの名前Trait
という命名規則に一致するメソッドが存在するならば、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
クエリービルダーオブジェクトを受け取り、そのスコープで付け加えたいwhere
節を追加してから、返す責任があります。remove
メソッドも「ビルダー」オブジェクトを受け取り、apply
により付け加えられたアクションを取り消してから、返す必要があります。言い換えれば、remove
は追加されたwhere
節(もしくは他の節)を削除しなくてはなりません。これにより、SoftDeletingScope
のメソッドは、次のようになります。The apply
method receives an Illuminate\Database\Eloquent\Builder
query builder object, and is responsible for adding any additional where
clauses that the scope wishes to add. The remove
method also receives a Builder
object 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
* @return void
*/
public function apply(Builder $builder)
{
$model = $builder->getModel();
$builder->whereNull($model->getQualifiedDeletedAtColumn());
}
/**
* 指定されたEloquentクエリービルダーからスコープを削除する
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return void
*/
public function remove(Builder $builder)
{
$column = $builder->getModel()->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
モデルを一つ持つとしましょう。この関係を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 Eloquent {
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 Eloquent {
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 Eloquent {
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 Eloquent {
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 Eloquent {
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 Eloquent {
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 Eloquent {
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 Eloquent {
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 Eloquent {
public function posts()
{
return $this->hasManyThrough('App\Post', '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 Eloquent {
public function posts()
{
return $this->hasManyThrough('App\Post', '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 Eloquent {
public function imageable()
{
return $this->morphTo();
}
}
class Staff extends Eloquent {
public function photos()
{
return $this->morphMany('App\Photo', 'imageable');
}
}
class Order extends Eloquent {
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 Eloquent {
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 Eloquent {
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 Eloquent {
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 Eloquent {
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(array('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(array('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');
関連したモデルの挿入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(array('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 = array(
new Comment(array('message' => 'A new comment.')),
new Comment(array('message' => 'Another comment.')),
new Comment(array('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();
関連したモデルの挿入 (Many To Many)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, array('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(array(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(array(1 => array('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(array('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, array('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 Eloquent {
protected $touches = array('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 = 'Edit to this comment!';
$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;
});
値でコレクションをソートするSorting A Collection By A Value
$roles = $roles->sortBy('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 Eloquent {
public function newCollection(array $models = array())
{
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 Eloquent {
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 Eloquent {
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 array('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 array();
}
属性の型変換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
、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
, 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);
配列と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 Eloquent {
protected $hidden = array('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 = array('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 = array('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.