こんにちは、かつコーチです。
Eloquent ORMとは?
LaravelのEloquent ORM(Object-Relational Mapping)は、
データベーステーブルをPHPのオブジェクトとして扱うことができる仕組みです。
EloquentはLaravelのモデルクラスと密接に関連しており、
データベースの各テーブルをモデルクラスとして表現し、
そのテーブルのレコード(行)をオブジェクトとして操作できます。
これにより、SQLの複雑なクエリを直接書かずに、
PHPコードだけでデータベース操作が可能になります。
Eloquentは非常に強力で、データベースとの連携をシンプルかつ柔軟にしつつ、
コードの可読性とメンテナンス性を向上させることができます。
Eloquent ORMの基本的な概念
- モデル: テーブルに対応するクラス(モデル)を作成し、そのクラスを通じてデータベースのレコードを操作します。各モデルは1つのテーブルに対応し、そのテーブルのレコードがオブジェクトとして表現されます。
- メソッドチェーン: Eloquentでは、メソッドチェーンを使って柔軟かつ直感的にクエリを構築できます。例えば、
where
やorderBy
などを繋げて、条件付きのクエリを簡単に書くことができます。 - リレーションシップ: Eloquentは、テーブル同士のリレーション(関係)を簡単に扱えるようにしています。1対1、1対多、多対多、ポリモーフィックリレーションなど、さまざまなリレーションを直感的に定義できます。
- スコープ: モデルにスコープを定義することで、よく使うクエリを再利用可能な形にまとめることができます。
Eloquentの基本的な使い方
モデルの作成
LaravelのEloquentでは、各テーブルに対応するモデルクラスを作成します。
以下のように、php artisan make:model
コマンドでモデルを作成します。
php artisan make:model User
上記のコマンドは、app/Models
ディレクトリ内にUser
モデルを作成します。
このモデルは、デフォルトでusers
というテーブルに対応しています。
テーブル名を変更したい場合は、モデル内でprotected $table
プロパティを使います。
データの取得
Eloquentでは、User::all()
などを使って簡単にデータベースのデータを取得できます。
// 全てのレコードを取得
$users = User::all();
// 条件付きで取得
$activeUsers = User::where('status', 'active')->get();
// 単一のレコードを取得
$user = User::find(1); // idが1のレコードを取得
データの挿入
新しいレコードをデータベースに挿入するには、Eloquentモデルのインスタンスを作成し、属性を設定して保存します。
$user = new User;
$user->name = 'John Doe';
$user->email = 'john@example.com';
$user->save();
または、create
メソッドを使って一度に挿入することも可能です。
この場合、モデルで$fillable
または$guarded
プロパティを定義して、
マスアサインメントを保護する必要があります。
User::create([
'name' => 'Jane Doe',
'email' => 'jane@example.com',
]);
データの更新
既存のレコードを更新するには、find
またはwhere
でレコードを取得してから、
属性を変更して保存します。
$user = User::find(1);
$user->name = 'John Smith';
$user->save();
データの削除
レコードを削除するには、delete
メソッドを使用します。
$user = User::find(1);
$user->delete();
Eloquentのリレーションシップ
Eloquentは、データベーステーブル間のリレーションシップを簡単に定義し
操作できる強力な機能を提供しています。
リレーションシップは、主に以下のように定義されます。
1対1 (One-to-One)
1つのモデルが他のモデルと1対1の関係を持つ場合、
hasOne
メソッドを使用してリレーションを定義します。
// Userモデル内
public function phone()
{
return $this->hasOne(Phone::class);
}
1対多 (One-to-Many)
1つのモデルが他の複数のモデルを持つ場合、hasMany
メソッドを使用します。
// Userモデル内
public function posts()
{
return $this->hasMany(Post::class);
}
多対多 (Many-to-Many)
多対多の関係はbelongsToMany
メソッドを使って定義されます。
このリレーションでは、中間テーブルを使ってレコード同士が結びつけられます。
// Userモデル内
public function roles()
{
return $this->belongsToMany(Role::class);
}
ポリモーフィックリレーション (Polymorphic)
ポリモーフィックリレーションを使用すると、
1つのモデルが複数の他のモデルと関係を持つことができます。
// Imageモデル内
public function imageable()
{
return $this->morphTo();
}
これにより、例えばposts
テーブルやcomments
テーブルでimages
テーブルとリレーションを持つことができます。
Eloquentの高度な機能
アクセサとミューテータ
アクセサとミューテータを使って、データベースから取得した値を自動的に整形したり、
データベースに保存する前に値を変換することができます。
// アクセサ(取得時にデータを整形)
public function getNameAttribute($value)
{
return ucfirst($value);
}
// ミューテータ(保存前にデータを変換)
public function setPasswordAttribute($value)
{
$this->attributes['password'] = bcrypt($value);
}
グローバルスコープ
グローバルスコープを使用すると、モデル全体に適用されるクエリの条件を定義できます。
class ActiveScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
$builder->where('status', 'active');
}
}
// モデル内で適用
protected static function booted()
{
static::addGlobalScope(new ActiveScope);
}
ソフトデリート
Eloquentのソフトデリート機能を使うと、レコードを実際に削除するのではなく、
deleted_at
カラムにタイムスタンプを記録して「削除された」ように扱います。
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model
{
use SoftDeletes;
}
イベント、リスナー、オブザーバー
Eloquentは、レコードのライフサイクルに応じてイベントを発生させることができます。
creating
やupdating
といったイベントにフックして、特定の処理を追加することができます。
User::creating(function ($user) {
$user->name = strtoupper($user->name);
});
Eloquentの利点と欠点
利点
- 直感的なAPI: メソッドチェーンを使ったクエリ作成や、リレーションシップの定義が簡単で、可読性が高い。
- 豊富な機能: リレーションシップ、スコープ、アクセサ、ミューテータ、イベントなど、モデルとデータベース操作を強力にサポートする機能が充実している。
- 自動的なデータ管理: タイムスタンプやソフトデリートなど、データの状態管理を自動化する機能が備わっている。
欠点
- パフォーマンスの問題: 複雑なリレーションシップや大量データを扱う場合、EloquentのパフォーマンスがSQLに比べて低下する可能性がある。特にN+1問題に注意が必要。
- 抽象化の限界: EloquentのAPIはシンプルだが、複雑なクエリや処理が必要な場合は、クエリビルダーや生のSQLに頼る必要がある場合がある。
まとめ
Eloquent ORMは、Laravel開発の中で非常に強力かつ柔軟なデータベース操作を提供してくれるツールです。
適切に使えば、データベースとアプリケーションのやりとりをシンプルにし、
開発効率を大幅に向上させることができます。