Laravelでドメイン別にルーティング

Laravelでドメインごとにルーティングを分ける方法は、公式ドキュメントにて丁寧に説明してあります。
その上で、実際に開発していく中で必要になった応用的な内容をまとめます。
## 基本形
https://readouble.com/laravel/10.x/ja/routing.html

公式ドキュメントから抜粋して追記
```php:routes/web.php
Route::domain('{account}.example.com')->group(function () {
    Route::get('user/{id}', function (string $account, string $id) {
        // accountとidのように、パスとドメインからパラメータを取得できる。
    });
    Route::post(...
    // ルーティングルールを列記していく
});
```
この例の場合、例えばECプラットフォームやブログサービスのように、アカウントごとにサブドメインを分けたりする時に便利に使えるかと思います。
サブドメインの一部をパラメータとして取得もできるため、サブドメイン別の処理も容易です。

一般利用者と管理者の利用する機能をドメインから別にしたいというような場合も複数のサブドメインルーティングのグループを作成することで実現できます。
```php:routes/web.php
Route::domain('viewer.example.com')->group(function () {
    Route::get('item/{id}', function (string $id) {
        return 'viewer world';
    });
    // ...
});

Route::domain('admin.example.com')->group(function () {
    Route::get('item/{id}', function (string $id) {
        return 'admin world';
    });
    // ...
});
```
### 確認方法
本筋とは少しそれますが、ルーティングキャッシュのクリアと、現在どのようなルーティングが設定されているかを確認するためのコマンドを記載しておきます。
```bash
// キャッシュのクリア
php artisan route:clear
// 現在のルーティングを確認
php artisan route:list
// 出力例(一部省略)
GET|HEAD  viewer.example.com/item/{id} ......
GET|HEAD  admin.example.com/item/{id} .......
```
サブドメインルーティングが設定されていると、リストにドメインから表示されます。

## ファイルを分ける場合
先の例だと、ルーティングの数が多くなった時に分かりにくくなってしまったり、ルールの追加ミスが発生する可能性が高くなってしまいます。
そこで、ドメイン別にファイルを分ける場合の方法を記載しておきます。

まず、ルーティングの設定は、RouteServiceProviderで定義されていますので、そちらのファイルを開きます。
そして、そこにサブドメインルーティングの設定と、対象とするファイルパスを指定します。

```php:app/Providers/RouteServiceProvider.php
// ... 省略
  public function boot(): void
  {
// ... 省略
    $this->routes(function () {
      // ルートグループの定義が行えるので、
      // 共通するミドルウェアやプレフィックスを指定する場合は、
      // こちらで定義する方がシンプルにできます。
      Route::domain('viewer.example.com')
        ->middleware('web')
        ->group(base_path('routes/viewer.php')); 
        
      Route::domain('admin.example.com')
        ->prefix('admin');
        ->group(base_path('routes/admin.php'));
        
      // デフォルトで存在するルートグループより前に記載しておかないと、
      // ドメインルートの同じURIが上書きしてしまいます。
      // デフォルトの内容が不要と判断される場合は、削除やコメントアウトしてください。
      Route::middleware('api')
      // ... 省略
    });
  }


```
これで、ファイルとドメインがひも付き、サブドメインルーティングの処理対象になります。
基本形と同じようにするには各ファイルに下記のように記述します。
```php:routes/viewer.php
<?php

use Illuminate\Support\Facades\Route;

Route::get('item/{id}', function (string $id) {
    return 'viewer world';
});
```

```php:routes/admin.php
<?php

use Illuminate\Support\Facades\Route;

Route::get('item/{id}', function (string $id) {
    return 'admin world';
});
```

### 情報の外部化
記事内では分かりやすさなどを優先して直接ドメインを記載していましたが、
実際は、環境によって変わる固有の情報をコード中に書くことは避けるかと思います。
この内容も本筋からは外れておまけ的なものですが、環境変数か.envに設定して読み込む例を記載します。
```.env
// ... 省略
DOMAIN_VIEWER=http://localviewer
DOMAIN_ADMIN=http://localadmin
// ... 省略
```
```php:app/Providers/RouteServiceProvider.php
// ... 省略
Route::domain(env('DOMAIN_VIEWER', 'localhost'))
// ... 省略
```

### ローカルで開発する時
これもおまけ情報です。
sailなどで、ローカル開発環境を立ち上げて確認する時、ドメインが2つであれば、localhostと127.0.0.1をそれぞれに割り当てることでサブドメインルーティングの動作確認が行なえます。
3つ以上の場合は、OSのhostsファイルに記述して確認します。

```hosts
// 例
127.0.0.1 localviewer
127.0.0.1 localadmin
127.0.0.1 localother
```

## さいごに
いろいろ蛇足を書いてしまったので、内容がボンヤリしてしまいましたが、
サブドメインルーティングはじめ、
Laravelのルーティングは少し工夫すれば、できることの範囲がグッと広がって面白いです。