プログラム関係の備忘録。技術系記事1000記事以上を目指すブログ

【Laravel5.6】Eloquent利用時にまず知っておきたいこと

  • 2018年5月29日
  • 2018年5月29日
  • PHP
  • 181view
  • 0件
PHP

使い始めのときに便利すぎて逆に混乱することが多かった為、ある程度触った今改めてまとめ。
過去の記事内容との重複箇所あり。
【Laravel】Eloquentを使ったデータベースの操作の基礎

とりあえずこういうものと覚える箇所

公式をちゃんと読んでおくとORMのEloquentの旨みが増える。

モデル名とテーブル名の関係

Eloquentでは明示的に指定しない限り、クラス名を複数形の「スネークケース」にしたものが、テーブル名として使用される。例えばShopというモデルを作るときは、勝手にshopsというテーブルを指定してくれる。
これに従った命名規則でテーブル設計を行っておくとわざわざEloquentでテーブルを指定する必要がなくなる。

明示的に指定する場合は以下のようにする

// 関連付けるテーブルを明示的に指定
protected $table = '(テーブル名)';

主キーの関係

主キーに関しても規約があり、idというカラムが主キーであると勝手に認識してくれる。
idが主キーではない場合には、オーバーライドする必要がある。

// 主キーを明示的に指定
protected $primaryKey = '(主キーのカラム名)';

リレーションの定義

テーブル同士をJOINするときの記述方法。
SQL書くのに慣れていると逆に混乱するかも。

以下2つのテーブルがある場合

ユーザーテーブル(主テーブル)
id
name
attribute

属性テーブル(従テーブル)
user_id
type

ユーザーモデルが属性モデル一つと関係している場合は、ユーザーモデルで属性メソッド(attribute)を設置し、hasOneメソッドを返す。

例1

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function attribute()
    {
        return $this->hasOne('App\Attribute');
    }
}

逆に属性モデルからユーザーモデルを取得する場合は、属性モデルでユーザーメソッドを設置し、belongsToメソッドを返す。

例2

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class Attribute extends Model
{
    public function user()
    {
        return $this->belongsTo('App\User');
    }
}

関連付け自体は上記のように単純だが、肝心のJOINするカラムを指定していない、のに上記でもうまくいくことになる。

その理由は、
例1ではEloquentでUserモデルはAttributeモデルがuser_id外部キーを持っていると仮定し、
例2ではEloquentでAttributeモデルはuser_idに一致するidを持つUserモデルを見つけようとするから。

要は勝手に関連する○○_idを見に行ったりしてくれる。
なのでこれについても命名規則に従うことでJOINするカラムの指定も省くことができる。

これが不本意な場合は第2引数、第3引数にカラムを指定することでオーバーライドすることもできる

public function user()
{
    return $this->belongsTo('App\User', 'foreign_key', 'other_key');
}

Eagerローディング

前項のようにテーブルが関連付けられている場合、いつものようにコントローラーで以下のようにデータを取得すると、まずは全ての本を取得し、そのあとその著者を取得するという処理になる為パフォーマンスがよくない。

$books = App\Book::all();

foreach ($books as $book) {
    echo $book->author->name;
}

そのときはwithメソッドを指定することで解消することができる

$books = App\Book::with('author')->get();

foreach ($books as $book) {
    echo $book->author->name;
}

複数のリレーションに対するwithメソッドの指定方法は、引数を追加で渡すだけ。

$books = App\Book::with(['author', 'publisher'])->get();