【Laravel】Serviceについて/Usecaseとの違い/簡単な実装

# 開発環境
Laravel10
Windows11
Postman

# Serviceとは
特定の機能やロジックを持つクラスを指す。アプリケーションの特定のビズネスロジックをまとめたもので、Controllerなどから呼び出される。

アプリケーションのロジックを整理し、モジュール化するためのデザインパターン(サービスパターン)を実装するためのもの。

例）ユーザー認証、メール送信、データ処理など
特定の機能を持つクラスをServiceとして実装する。

## サービスパターンとは

特定のビジネスロジックをサービスクラスに移動させることで、ControllerやModelからそのロジックを分離させるデザインパターンのこと。

## メリット
コードを分散さでることで、コードの再利用性向上、FatControllerになることを防ぐ。可読性、保守性の向上。

## 用途
>ブレードやコントローラの中で呼び出す関数やプロパティを定義できる。使い方は自由度が高く、例えば以下があげられる。

>・コントローラの処理をサービスに移行する
・ルート名によってmeta情報の適用を変更する
・メール送信用の本文を作成する
・チャットにメッセージを投げる
・APIのデータを取得する
[引用：https://qiita.com/shizen-shin/items/d9fe0358617092ac6984]

# Usecaseとの違い

## Service
✧概要
目的：ビジネスロジックをコントローラやモデルから分離し、再利用可能でテストしやすい形にする。

スコープ：一連の関連するビジネスロジックや操作をまとめて管理。

責務：あるドメインや機能に関連する複数の操作をまとめる。
例）
ユーザー管理、注文処理

✧特徴
抽象度：高い抽象度で複数の関連b操作をまとめる。

再利用性：同じサービスを複数のコントローラやコンポーネントで利用できる。

構成：通常は複数のメソッドを持ち、それぞれが関連するビジネスロジックを実装。

## Usercase
✧概要
目的：特定のビジネスロジックや操作を一つのユースケース（シナリオ）として独立させる。

スコープ：１つの特定の操作やフローに焦点を当てる。

責務：特定のビジネスロジックを１つのクラスやメソッドにまとめることで、単一責任を持たせる・

✧特徴
抽象度：低い抽象度で特定の操作やシナリオに焦点を当てる。

再利用性: 1つの特定の操作に対して明確な責任を持つため、他の操作とは独立している。

構成: 通常は1つのメソッドまたはクラスが1つのビジネスロジックを実装。

# ServiceとUsecaseの使いわけ
1.Servece
・同じドメイン内で複数の操作をまとめて管理したい場合。
・コントローラが特定のドメインに関連する複数の操作を必要とする場合。
例: ユーザー管理、注文管理など。

2.Usecase
・特定の操作やビジネスロジックにフォーカスしたい場合。
・単一責任を徹底し、1つのクラスやメソッドが1つのユースケースに対応する場合。
例: ユーザー登録、パスワードリセットなどの単一の操作。

# サービスコンテナとの違い
✧結論
サービスコンテナ：Laravelの依存性注入を管理する仕組み。サービスの登録や解決を行う。

Service：特定のビジネスロジックや機能をまとめたクラス。アプリケーションの各部分から利用される。

サービスコンテナはServiceクラスを含む依存オブジェクトの管理と提供を行う。Serviceクラスは具体的なビジネスロジックを実装。

→サービスコンテナがServiceクラスのインスタンスを管理することで、密接に関係する。

## サービスコンテナ
Laravelの依存性注入を実現する仕組み。クラスが必要とする依存オブジェクトを自動的に注入することで、クラス同士の結びつき緩やかにし、コードの再利用性やテスト容易性を高める。

✧機能
依存注入：クラスのコントラクタに必要な依存オブジェクトを自動的に提供。

サービスプロバイダー：サービスコンテナにサービスを登録する。

リゾルビング：登録されたサービスを必要なタイミングで生成。


# 実装の流れ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/1f6a130e-05f5-803a-22cd-97e8759d5029.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/6583e0f6-cc8f-874d-cc00-0ee6c59b6016.png)

[引用：https://aizulab.com/blog/laravel-service-repository/]

◎Serviceで行うこと
1.Repositoryに、Controllerから受け取ったデータを渡す。
2.Repositoryから返ってきたデータを整形し、Controllerに返す。

# 実装

## Controller

```php:WorkController.php
<?php

namespace App\Http\Controllers\APi;

use Illuminate\Http\Request;
use App\Services\WorkService;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;

class WorkController extends Controller
{
    public function __construct(
        private readonly WorkService $workService
    ){
    }

    public function getWorks(): JsonResponse
    {
        $works = $this->workService->getWorkList();

        return response()->json($works);
    }
}
```

## Service
```php:WorkService.php
<?php

namespace App\Services;

use App\Models\Work;
use App\Repositories\Interfaces\WorkRepositoryInterface;

class WorkService
{
    public function __construct(
        private readonly WorkRepositoryInterface $workRepository
    )
    {
    }

    public function getWorkList() :array
    {
        $works = $this->workRepository->findAllWorks();

        return $works->map(function (Work $work): array{
            return [
                'work_id' => $work->id,
                'name' => $work->name,
            ];
        });
    }
}

```
## Repository
```php:WorkRepository.php
<?php

namespace App\Repositories;

use App\Repositories\Interfaces\WorkRepositoryInterface;
use App\Models\Work;
use Illuminate\Support\Collection;

class WorkRepository implements WorkRepositoryInterface
{
    public function __construct(
        private readonly Work $model
    ){
    }

    public function findAllWorks(): Collection
    {
        return $this->model::get();
    }
}

```

# 参考記事

https://qiita.com/shizen-shin/items/d9fe0358617092ac6984

https://aizulab.com/blog/laravel-service-repository/