Open4

Laravelはじめ

Sut103Sut103

環境構築

基本

以下2点が必要

  • PHP
  • Composer

Laravel Sail

ローカルに用意しなくても簡単にコンテナ上で実行できて楽

curl -s https://laravel.build/example-app | bash
cd example-app
./vendor/bin/sail up
  • example-appは任意で変更
  • クエリでmysql, pgsql, mariadb, redis, memcached, meilisearch, minio, selenium, mailpit のコンテナもまとめて作れる
  • クエリでdevcontainerも作ってくれる

https://laravel.com/docs/10.x/sail

Sut103Sut103

SailはLaravel 8から対応しているらしい。
それ以前のバージョンでは手動でdocker-compose.ymlを作れば似たようなことはできるだろう。

Sut103Sut103

公式ドキュメントを読む

公式ドキュメントで基本的な概念を確認してみた。
最新バージョン(Laravel 10)のドキュメントを読んだが、以前のバージョンでも基礎は共通しているだろう(たぶん)

ライフサイクル

  • リクエストのエントリポイントとなるのはpublic/index.php
  • public/index.phpはComposerの作成したオートローダー定義をロードし、bootstrap/app.phpからサービスコンテナのインスタンスを作成する
  • 最初のHTTPリクエスト(?)はHTTP Kernel(app/Http/Kernel.php)にルートされ、config/app.phpに設定されたサービスプロバイダが作成、登録、起動される。また、カーネル毎のミドルウェアや環境もロードされている。
  • サービスプロバイダのうち、app/providers/RouteServiceProviderはroutes/を参照してリクエストのルーティングを決定する。この際にルート毎のミドルウェアが適用される。
  • リクエストはルーティングに従いコントローラーに渡され、レンスポンスが返る。この際にもミドルウェアを通過する。

サービスコンテナ

クラスでの自動DI

公式ドキュメントの例.php
<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use App\Repositories\UserRepository;
use App\Models\User;
use Illuminate\View\View;
 
class UserController extends Controller
{
    /**
     * Create a new controller instance.
     */
    public function __construct(
        protected UserRepository $users,
    ) {}
 
    /**
     * Show the profile for the given user.
     */
    public function show(string $id): View
    {
        $user = $this->users->find($id);
 
        return view('user.profile', ['user' => $user]);
    }
}
  • UserControllerクラスの中でUserRepositoryクラスのfindメソッドが使いたいなぁ
  • ということで、UserControllerのコンストラクタでUserRepositoryのインスタンスを注入している
  • 本来はUserRepositoryのインスタンスを明示的に作る必要があるが、ここではサービスコンテナが自動的に依存解決するため宣言のみの記述で済んでいる。(たぶん。)
  • $usersはUserRepositoryクラスを満たしていればモックなどに置換できて便利(?)

クロージャでの自動DI

公式ドキュメントの例.php
<?php
 
class Service
{
    // ...
}
 
Route::get('/', function (Service $service) {
    die($service::class);
});
  • この例ではRoute::getのクロージャが、先程のshow()の立ち位置
  • 先程はクラスのコンストラクタでDIをしていたが、その記述がない。
  • クロージャの引数としてサービスコンテナの依存解決を利用している(?)

結合(サービスコンテナへの登録)

公式ドキュメントでの例.php
use App\Services\Transistor;
use App\Services\PodcastParser;
use Illuminate\Contracts\Foundation\Application;

$this->app->bind(Transistor::class, function (Application $app) {
    return new Transistor($app->make(PodcastParser::class));
});
  • 前掲2つのようにシンプルな依存解決でなければサービスコンテナに登録が必要
  • 基本的にはサービスプロバイダ内で行う
  • appでサービスコンテナへアクセスできる
  • bind()を用いてTransisterの依存解決にPodcastParserインスタンスを含むTransisterインスタンスを結合している

サービスプロバイダ

app/providers/配下にある。

register()

  • サービスコンテナへの登録を行うところ(前述)
  • それ以外はしない

boot()

  • サービスコンテナ起動完了時に実行する処理

サービスプロバイダの登録

  • config/app.php のproviders[]にて
config/app.php
    'providers' => ServiceProvider::defaultProviders()->merge([
        /*
         * Package Service Providers...
         */

        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,
    ])->toArray(),