CHANSHIGELOG

いろんなこと

Laravelでもhal+jsonでレスポンスを返したい

前回、SymfonyのHalJsonResponseBundleを作っている話に関連して、Laravelでもhal+json形式のレスポンスを使えるようにしたく、先にこちらをライブラリ(コンポーネント)化しました。

packagist.org

※LaravelではsubRequestの考え方が取り込まれてないので、他のリソースを埋め込むembedded機能は作ってません。
※Laravel9のみサポートしてます。

メジャーバージョンとして公開していませんが、実際に使うことができます。

使い方としては至って簡単で、まずはインストールしていただくと、Laravelのパッケージディスカバリ機能でHalJsonResponseProviderが自動登録されます。

composer require chanshige/laravel-hal-json-response

※ composer.jsonのextraにて定義しています

HalJsonResponseProviderでは、インターフェースとそれを実装した具象クラスを結合し、サービスコンテナに登録するまでをやっています。

<?php

declare(strict_types=1);

namespace Chanshige\Laravel\Http;

use Chanshige\Laravel\Http\Contracts\HalJsonResponseInterface;
use Chanshige\Laravel\Http\Contracts\HalLinkInterface;
use Illuminate\Support\ServiceProvider;

final class HalJsonResponseProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->singleton(HalLinkInterface::class, HalLink::class);
        $this->app->bind(HalJsonResponseInterface::class, HalJsonResponse::class);
    }
}

続けてController(Action)を作りますが、例ではコンストラクタでHalJsonResponseInterfaceをとってます。 併せて、HalLinkアトリビュートで usersリソースのリンクを(存在するテイで)貼ってみます。

final class IndexController
{
    public function __construct(
        private HalJsonResponseInterface $response
    ) {
    }

    #[Get(uri: '/', name: 'index')]
    #[HalLink(rel: 'user', href: '/users/{user_id}')]
    public function __invoke(): Responsable
    {
        return $this->response->withContent(
            [
                'greeting' => 'Hi!',
                'user_id' => 1989,
            ]
        );
    }
}

Laravelのサービスコンテナ(DI)は自動依存注入(Auto Wiring)機能があるので便利ですね。コンストラクタインジェクション! (Facadeは使わない派です....)

これだけでindexリソースにリクエストすると、以下のようなbodyが返ってきます。

< Content-Type: application/hal+json

{
    "greeting": "Hi!",
    "user_id": 1989,
    "_links": {
        "self": {
            "href": "/"
        },
        "user": {
            "href": "/users/1989"
        }
    }
}

お気づきかと思いますが、userリソースのリンク"href": "/users/1989"は、bodyの'user_id' => 1989'に置き換えられるようになってます。 こちらはHalLinkアトリビュートで指定している href:'/users/{user_id}'を基にURIを生成して反映しています。

リソース同士を紐づける際、より関連づいていることを証明できそうな気がしたので実装に含めています。
※この辺りはBEAR.Sundayを超参考にしました。

もうちょっと調整して、メジャーリリースしようと思います!