LaravelでService層とRepository層を取り入れる


Laravelを使用したプロジェクトでServiceとRepositoryというLaravelの機能を使用する機会があったので、備忘録の意味も含めて紹介したい。

対象読者

  • 実務に入って間もない方

Service、Repository、Controller、Modelの関係性

今回は下記の流れになる

Controller →Service →Repository →Model

【Controller】
①ControllerからServiceをインスタンス化し、メソッドを呼び出す
❻Serviceから返ってきた整形されたデータをフロントに渡す

【Service】
②Repositoryのメソッドを呼び、Controllerから受け取ったIDなどのデータを渡したりする
❺Repositoryから返ってきたデータを整形し、Controllerに返す

Repository】
③クエリを記述してDBからデータを取得する
❹Modelから取得したデータをServiceに返す

Service層とRepository層を取り入れるメリット、デメリット

メリット

・DB操作をControllerで行わない事によりControllerのコード数が増える、いわゆるファットコントローラーになる事を回避できる。

・処理を分担する事により、可読性、保守性が向上する。

デメリット

・中〜大規模プロジェクト向けという事もあり、小規模プロジェクトでは処理を分ける事に煩わしさを感じる可能性がある

実際にやってみる

実行環境

  • OS : Mac Intelチップモデル
  • Laravel8
  • PHP8.0

テーブル構成はのようにしてみる

idnamecreated_atupdated_atdeleted_at
1りんご2022-01-012022-01-01null
2バナナ2022-01-022022-01-02null
3ぶどう2022-01-032022-01-032022-01-03

ディレクトリ構造

Controllerを作成

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Services\FruitService;

class FruitController extends Controller
{

    public function getFruits() {

        //FruitServiceをインスタンス化
        $service = new FruitService;

        //FruitServiceのgetFruitListを呼び出す
        $fruits = FruitService::getFruitList();
 
        return $fruits;
    }
}

Serviceクラスを作成

<?php
namespace App\Services;

use App\Repositories\fruitRepository;

class fruitService
{

    // フルーツ一覧取得
    public function getFruitList()
    {
        //fruitRepositoryのfindAllFruitを呼び出し、取得
        $fruits = fruitRepository::findAllFruit()->get();
        return $fruits;
    }

}

Repositoryを作成

<?php

namespace App\Repositories;

use App\Models\Fruit;

class FruitRepository
{
    public static function findAllFruit()
    {
        $fruit = Fruit::from('fruits')
                ->select(
                    'fruits.id as fruit_id',
                    'fruits.name as fruit_name')
                ->where('fruits.deleted_at', '=', null)
                ->orderBy('fruits.id','ASC');

        return $fruit;
    }
}

Modelを作成

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Fruit extends Model
{
    use SoftDeletes;
    use HasFactory;

    protected $primaryKey = 'id';
    protected $guarded    = ['id'];
    protected $dates = ['deleted_at'];

    public $incrementing = true;

}

実行結果

まとめ

以上がService層とRepository層を取り入れた実装方法となる。

今回は基礎的な処理のみの為、恩恵は感じ辛いかも知れないが実際に取り入れて頂ければ可読性、保守性の高さを実感して頂けると思う。

今後のプロジェクトでLaravelを使用する機会があった際には、積極的に採用していきたい。


Leave a Reply

Your email address will not be published. Required fields are marked *