こんにちは、かつコーチです。
前回はMigrationを使って、テーブル構造をコードで管理する方法を解説しました。
テーブルが作れるようになったら、次はそのテーブルのデータをPHPのコードから読み書きする番です。
今回はLaravelの中でも特に人気の高い機能、「Eloquent(エロクアント)」というORMについて解説します。
Eloquentとは?
ORMという考え方
ORMとは「Object-Relational Mapping」の略で、データベースのテーブルをPHPのオブジェクト(クラスのインスタンス)として扱えるようにする仕組みのことです。
ORMを使わない場合、データベースを操作するにはSQL文を自分で組み立てる必要があります。
// ORMを使わない場合:SQLを自分で書く
$pdo = new PDO('mysql:host=localhost;dbname=blog', 'root', '');
$stmt = $pdo->prepare('SELECT * FROM posts WHERE is_published = ?');
$stmt->execute([true]);
$posts = $stmt->fetchAll(PDO::FETCH_ASSOC);
Eloquentを使うと、これと同じ処理をPHPのオブジェクトとして直感的に書けるようになります。
// Eloquentを使う場合:PHPのコードとして書ける
$posts = Post::where('is_published', true)->get();
SQLを意識しなくても、Post というクラスに対してメソッドを呼び出す感覚でデータを取得できるのが、Eloquentの大きな魅力です。
モデルとテーブルの対応関係
Eloquentでは、1つのテーブルに対して1つのモデルクラスを用意します。
Laravelの命名規則では、テーブル名は複数形のスネークケース(posts)、モデル名はその単数形のパスカルケース(Post)に対応します。
// app/Models/Post.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
//
}
たったこれだけのコードで、Post モデルは posts テーブルに自動的に結びつきます。
命名規則に沿っている限り、「このモデルはどのテーブルと対応しているか」を自分で書く必要はありません。
モデルファイルは、次のArtisanコマンドで生成できます。
php artisan make:model Post
Eloquentの基本的な使い方
データを取得する(Read)
まずは、データを取得する代表的なメソッドを見てみましょう。
// 全件取得
$posts = Post::all();
// 主キーで1件取得(見つからなければnull)
$post = Post::find(1);
// 主キーで1件取得(見つからなければ404エラー)
$post = Post::findOrFail(1);
// 条件を指定して絞り込む
$posts = Post::where('is_published', true)->get();
// 条件を指定して1件だけ取得する
$post = Post::where('title', 'Laravel入門')->first();
where() に続けて get() を呼ぶと複数件、first() を呼ぶと最初の1件だけが返ってくる、という違いを覚えておくと迷いません。
データを保存する(Create)
新しいレコードを保存するには、モデルのインスタンスを作って save() を呼び出します。
$post = new Post();
$post->title = 'Eloquent入門';
$post->body = 'Eloquentの基本を解説します。';
$post->is_published = true;
$post->save();
もう少し簡潔に書きたい場合は、create() メソッドでも同じことができます。
$post = Post::create([
'title' => 'Eloquent入門',
'body' => 'Eloquentの基本を解説します。',
'is_published' => true,
]);
データを更新する(Update)
既存のレコードを更新する場合も、直感的な書き方ができます。
$post = Post::findOrFail(1);
$post->title = '更新後のタイトル';
$post->save();
// またはupdate()でまとめて更新する
$post = Post::findOrFail(1);
$post->update(['title' => '更新後のタイトル']);
データを削除する(Delete)
削除も同様に、モデルに対して delete() を呼び出すだけです。
$post = Post::findOrFail(1);
$post->delete();
このように、SQLの SELECT INSERT UPDATE DELETE に対応する操作が、get() create() update() delete() というPHPらしいメソッド名で統一されているのが、Eloquentの読みやすさにつながっています。
create() を使うために必要な設定
$fillable プロパティの指定
Eloquentには、意図しないカラムを一括更新されないようにする安全機構が備わっています。
そのため、create() を使うには、モデル側で「一括代入を許可するカラム」を明示する必要があります。
// app/Models/Post.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
/**
* 一括代入を許可するカラム
*/
protected $fillable = ['title', 'body', 'is_published'];
}
私が初めて create() を使ったとき、この設定を知らずにハマった経験があります。
$post = Post::create([
'title' => 'Eloquent入門',
'body' => 'Eloquentの基本を解説します。',
]);
$fillable を設定していない状態でこのコードを実行したところ、MassAssignmentException という例外が発生しました。
エラーメッセージには「一括代入できません」というようなことが書かれていたのですが、当時の私は「なぜ普通に値を渡しているだけなのに弾かれるのか」が理解できず、しばらく検索することになりました。
理由を調べてみると、これはユーザーからの入力をそのまま create() に渡した際に、意図しないカラム(例えば管理者権限を表す is_admin など)まで書き換えられてしまう事故を防ぐための仕組みだと分かりました。
セキュリティ上とても理にかなった仕様なのですが、初見では「不便な制限」に感じてしまいがちなポイントです。
つまずきやすいポイント:モデル名とテーブル名の不一致
命名規則から外れたテーブルを扱うとき
Eloquentは命名規則を頼りにテーブルを自動判定するため、その規則から外れるテーブルに対しては注意が必要です。
❌ Before:命名規則に沿っていないテーブル名で何も指定しない
// テーブル名が post_data という命名規則外の名前になっている
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
// このままだと自動的に post_data ではなく posts を探しにいってしまう
}
このままだと、Eloquentは Post モデルに対して自動的に posts テーブルを探しにいくため、「テーブルが存在しません」というエラーになります。
✅ After:$table プロパティでテーブル名を明示する
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
/**
* このモデルに対応するテーブル名
*/
protected $table = 'post_data';
}
$table プロパティで対応するテーブル名を明示すれば、命名規則から外れたテーブルでも問題なくEloquentを使えます。
とはいえ、特別な事情がない限りは、素直に命名規則に沿ったテーブル名・モデル名にしておく方が、コードを書くときも読むときも迷いが少なくて済みます。
一歩先の使い方:クエリを組み立てる
条件を複数つなげる
Eloquentのクエリはメソッドチェーンでつなげられるため、複数の条件を組み合わせるのも簡単です。
$posts = Post::where('is_published', true)
->where('title', 'like', '%Laravel%')
->orderBy('created_at', 'desc')
->limit(10)
->get();
where() を複数つなげると、それぞれの条件が「かつ(AND)」で結合されます。
orderBy() で並び順、limit() で取得件数の上限を指定できるところも、SQLを知っていればすぐに馴染める設計になっています。
このように、単純な検索から複雑な条件の絞り込みまで一貫した書き方でできるのが、Eloquentが「Laravelの顔」と言われる理由です。
まとめ
この記事のポイント
- Eloquentは、テーブルをPHPのオブジェクトとして扱えるようにするORM機能
- モデル名とテーブル名の命名規則(単数形パスカルケース⇔複数形スネークケース)を守れば、対応関係は自動で決まる
get()create()update()delete()など、SQLの操作に対応したメソッドが用意されているcreate()を使うには$fillableでカラムを許可しないとMassAssignmentExceptionが発生する- 命名規則から外れたテーブル名は
$tableプロパティで明示できる
次に読むべき記事
Eloquentの基本操作が分かったところで、次はテーブル同士を結びつける「リレーション」について解説します。
→ 次の記事:Eloquentのリレーション:hasMany・belongsToの使い分け
