LoginSignup
275

More than 5 years have passed since last update.

Eloquentに惚れちゃう便利な機能

Last updated at Posted at 2016-02-20

1. アクセサでデータを作成

DBに存在しないアトリビュートをJSONのレスポンスで吐き出しができます。ゲッターとセッターを使うのは元々可能ですけど、アクセサで作られるアトリビュートがデフォルトでJSONになりません。そういうときは$appendsが助けてくれます!

<?php
class Store extends Model
{
    $appends = ['products_count']; // ← ここを追加すると

    public function getProductsCountAttribute()
    {
        // 複数クエリーに気をつけてください :)
        return $this->product()->count();
    }
}

class StoresController extends Controller 
{
    public function index()
    {
        return Store::all(); 
        // products_countも一緒に表示されます
    }
}

2. クエリースコープ

複雑な条件があるとコードが汚くなる可能性が高くなりますね。それぞれのクエリーの条件をスコープにすれば、別々になるおまけに、メソッド名から理解できるようになります。

スコープを使って綺麗なクエリーを書きましょう!

<?php

// モバイルの大きな発売の取得
Order::bigSales()
    ->fromMobile()
    ->get();

// 先週モバイルで行われた1000円以上の発売の取得
Order::totalGreaterThan(1000)
    ->fromMobile()
    ->lastWeek()
    ->get();

class Order extends Model
{
    public function scopeBigSales($query)
    {
        return $query->totalGreaterThan(5000);
    }

    public function scopeTotalGreaterThan($query, $total)
    {
        return $query->where('total', '>', $total);
    }

    public function scopeFromMobile($query)
    {
        return $query->whereIn('source', ['phone', 'tablet']);
    }

    public function scopeLastWeek($query)
    {   
        return $query->where('created_at', Carbon::now()->subWeek());
    }
}

3. グローバルスコープも可能です

ユーザーは自分のポストしか見れないとか?簡単です!

ログインしているユーザーのみの結果がほしい場合、グローバルスコープが有効です。

class Post extends Model
{
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope('my_posts', function(Builder $builder) {
            // ログインしてるユーザーのみ
           $builder->where('user_id', auth()->id());
        });
    }
}

一年以上前の古いデータを隠すとか?

class Order extends Model
{
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope('last_year_only', function(Builder $builder) {
            // 去年から取得する
           $builder->where('created_at', '>', Carbon::now()->subYear());
        });
    }
}

もちろん、古いデータが必要だったらとか、他のユーザーのポストが必要だったらとか、グローバルスコープを外すことができます。

// 今年のデータに限るスコープを外す
Order::withoutGlobalScope('last_year_only')->get();

// 全てのスコープを外す
Order::withoutGlobalScopes()->get();

4. イベントも簡単です!

Laravelが発火するイベントは下記のようです。

イベント名 説明
creating 作成するとき
created 作成したとき
updating 更新するとき
updated 更新したとき
saving 保存するとき(制作でも、更新でも)
saved 保存したとき(制作でも、更新でも)
deleting 削除するとき
deleted 削除したとき
restoring ソフト削除をレストアするとき
restored ソフト削除をレストアしたとき

使い方もとても簡単です。グローバルスコープのように、boot()で登録するといいです。

class Order extends Model
{
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($order) { // 作成するときに
            // falseをリターンしたら作成されません
            return $order->isValid(); 
        });

        static::created(function ($order) { // 作成したときに
            $order->sendOrderSubmittedEmail();
        });
    }
}

Special Thanks

  • 記事書くようにインスパイアしてくれたたくわんさん
  • 推敲に手伝ってくれたMaxmellonさん

ありがとうございます!! :D

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
275