11
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Laravel】 ModelクラスからQueryBuilderクラスを分離させる

Last updated at Posted at 2020-01-27

概要

LaravelだとGlobalScopeを作成して、scopeメソッドをModelクラスから分離させることができる。

しかし、Eloquentに依存してしまうため、DBファサード等を使用してQueryBuilderのみを使用する場合に、クエリの分割ができない。

そのため、Illuminate\Database\Query\Builder クラスを継承したQueryBuilderクラスを作成し、EloquentからでもQueryBuilderのみでも利用できるようにする。

実装

QueryBuilderクラスの作成

Illuminate\Database\Query\Builderしたクラスを作成する。


<?php

namespace App\Models\Builder;

use Illuminate\Database\Query\Builder;

class UserBuilder extends Builder
{
    public $from = 'users';

    public function verified()
    {
        return $this->whereNotNull('email_verified_at');
    }
}

EloquentModel修正

EloquentModelで作成したQueryBuilderクラスを呼び出せるようにする。

Illuminate\Database\EloquentクラスのnewBaseQueryBuilderメソッドをオーバーライドし、先程作成したQueryBuilderクラスを返却するように変更する。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Models\Builder\UserBuilder;

class User extends Model
{

    /**
     * @return \App\Models\Builder\UserBuilder
     */
    public function newBaseQueryBuilder()
    {
        return new UserBuilder($this->getConnection());
    }

Builderクラスにマクロを定義

Illuminate\Database\Query\Builderクラスに、queryメソッドをマクロとして定義する。
queryメソッドでは、コネクションを引数に自身のインスタンス生成し、返却するように修正する。

<?php

namespace App\Providers;

use Illuminate\Database\Query\Builder;
use DB;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Builder::macro('query', function () {
            return new self(DB::connection());
        });
    }

使用例

例1. EloquentModelで使用する場合

scopeメソッドのように利用するだけでOK!

<?php

namespace App\Http\Controllers;

use App\Models\User;

class UserController extends Controller
{
    public function index()
    {
        $users = User::verified()->get();

    }
}

例2. QueryBuilderのみで使用する場合

queryメソッドを呼んだあとに、チェーンして呼べばOK!

<?php

namespace App\Http\Controllers;

use App\Models\Builder\UserBuilder;

class UserController extends Controller
{
    public function index()
    {
        $users = UserBuilder::query()->verified()->get();

    }
}

まとめ

クエリ生成に関する部分をクラスとして独立させたことで、EloquentでもQueryBuilderでも使用できるようにしました。

11
6
0

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
11
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?