# サービスコンテナとサービスプロバイダ ## 一般的な構成の場合 - コントローラクラス - サービスクラス - モデルクラス 以下に、サービスコンテナ、サービスプロバイダ、サービスクラス、コントローラクラス、モデルクラスを使用したコード例を示します。 1.サービスクラスの作成 ```php // app/Services/PostService.php namespace App\Services; use App\Models\Post; class PostService { public function getAllPosts() { return Post::all(); } } ``` 2.サービスプロバイダの作成と登録 ```php // app/Providers/PostServiceProvider.php namespace App\Providers; use Illuminate\Support\ServiceProvider; use App\Services\PostService; class PostServiceProvider extends ServiceProvider { public function register() { $this->app->singleton(PostService::class, function ($app) { return new PostService(); }); } public function boot() { // } } ``` 3.config/app.php の providers 配列に PostServiceProvider を追加して登録します。 ```php // config/app.php 'providers' => [ // ... App\Providers\PostServiceProvider::class, ], ``` 4.モデルクラスの作成 ```php // app/Models/Post.php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Post extends Model { protected $fillable = ['title', 'body']; } ``` 5.コントローラクラスの作成 ```php // app/Http/Controllers/PostController.php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Services\PostService; class PostController extends Controller { protected $postService; public function __construct(PostService $postService) { $this->postService = $postService; } public function index() { $posts = $this->postService->getAllPosts(); return view('posts.index', compact('posts')); } } ``` 6.ルーティングの設定 ``` // routes/web.php use App\Http\Controllers\PostController; Route::get('/posts', [PostController::class, 'index']); ``` このコード例では、PostService サービスクラスを作成し、PostServiceProvider でサービスコンテナに登録しています。PostController コントローラクラスでは、コンストラクタインジェクションを使用して PostService のインスタンスを取得し、ビジネスロジックを実行しています。最後に、ルーティングでコントローラの index メソッドにリクエストをディスパッチしています。 記の例では、サービスプロバイダを使用してサービスコンテナへの登録を行っていますが、Laravelではサービスコンテナが自動的にクラスの依存関係を解決し、インスタンスを生成できます。従って、サービスプロバイダの作成とサービスコンテナへの登録がなくても、このケースでは動作します。 ## サービスプロバイダとサービスコンテナが生かせる場合 異なる実装やインターフェースを使用する場合の具体例として、メール送信機能を考えます。メール送信機能には、さまざまなメールサービス(SMTP、SendGrid、Mailgun など)を使用することができます。インターフェースと異なる実装を用いて、アプリケーションの構成を簡単に変更できるようにします。 1.インターフェースの作成 ```php // app/Contracts/Mailer.php namespace App\Contracts; interface Mailer { public function send(string $to, string $subject, string $body); } ``` 2.異なる実装の作成 SMTPを使った実装: ```php // app/Services/SmtpMailer.php namespace App\Services; use App\Contracts\Mailer; class SmtpMailer implements Mailer { public function send(string $to, string $subject, string $body) { // SMTPを使ってメールを送信するロジック } } ``` 3.SendGridを使った実装: ```php // app/Services/SendGridMailer.php namespace App\Services; use App\Contracts\Mailer; class SendGridMailer implements Mailer { public function send(string $to, string $subject, string $body) { // SendGridを使ってメールを送信するロジック } } ``` 4.サービスプロバイダの作成と登録 ```php // app/Providers/MailServiceProvider.php namespace App\Providers; use Illuminate\Support\ServiceProvider; use App\Contracts\Mailer; use App\Services\SmtpMailer; use App\Services\SendGridMailer; class MailServiceProvider extends ServiceProvider { public function register() { $this->app->singleton(Mailer::class, function ($app) { // 実装を切り替えるための条件分岐 $mailer = config('mail.mailer'); if ($mailer === 'smtp') { return new SmtpMailer(); } elseif ($mailer === 'sendgrid') { return new SendGridMailer(); } throw new \Exception('Invalid mailer configuration.'); }); } public function boot() { // } } ``` 5.config/app.php の providers 配列に MailServiceProvider を追加して登録します。 ```php // app/Http/Controllers/MailController.php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Contracts\Mailer; class MailController extends Controller { protected $mailer; public function __construct(Mailer $mailer) { $this->mailer = $mailer; } public function sendMail() { $to = 'example@example.com'; $subject = 'Test Mail'; $body = 'This is a test mail.'; $this->mailer->send($to, $subject, $body); return 'Mail sent.'; } } ``` この例では、メール送信機能のインターフェースMailerを定義し、異なる実装(SmtpMailerSmtpMailer と SendGridMailer)を作成しました。MailServiceProvider を使って、アプリケーションの設定に基づいて実装を切り替えることができます。 この方法の利点は、メール送信機能を使用するすべての箇所でインターフェース Mailer を使ってコーディングすることで、実装が柔軟に切り替えられる点です。例えば、メール送信サービスを変更したい場合、config/mail.php の設定を変更するだけで、アプリケーション全体で新しいメール送信サービスが適用されます。 サービスプロバイダとサービスコンテナを使用することで、アプリケーションの依存関係が一元管理され、コードの整理やメンテナンスが容易になります。また、アプリケーションの構成を変更することで、実装を簡単に切り替えることが可能です。