💭

Laravel 新コンポーネントのちょっとした注意点

2021/04/27に公開

前置き

Laravelの新バージョンのリリース間隔が1年に変更になったのに伴いVer.8のセキュリティFixは、LTSのVer.6と同じ2022年9月6日までとなりました。Laravel6を積極的に使う理由も無くなり、次のVer.9が出るまでは、Ver.8が今まで以上に使われてくるのではないでしょうか(たぶん)。

それはさておき、Ver.7から登場した新コンポーネントで、ちょっとした注意点というか、予め知っておくと、トラブった際に苦労しなくて済むかも知れない話です。

新コンポーネントでは、クラスベースと匿名のコンポーネントがありますが、今回の話は、クラスベースが該当します。

(以下、動作確認済みVersionは、Laravel 8.38.0 です)
(新コンポーネントの知識はある前提で進めていますのでご了承下さい)

問題発生方法

Laravelをインストールし、以下のコマンドでコンポーネントを作成します。

php artisan make:component Alert

すると、app/View/Components に Alertというコンポーネントクラスと、resources/views/components/alert.blade.php が出来上がります。
その後、最初から用意されている views/welcome.blade.php を以下のように編集します。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

    <x-alert name="taro" />

</body>
</html>

そしてブラウザでアクセスして開きます。特に出力する内容が無いので、白い画面が表示されます。続けて、Alertクラスで、name を受け取るよう以下のように変更します。

class Alert extends Component
{
    public $name;

    /**
     * Create a new component instance.
     *
     * @return void
     */
    public function __construct($name)
    {
        //
        $this->name = $name;
    }
}

再度ブラウザでアクセスします。すると以下のような感じのエラーが出ます。

Illuminate\Contracts\Container\BindingResolutionException
Unresolvable dependency resolving [Parameter #0 [ <required> $name ]] in class App\View\Components\Alert (View: /...path.../resources/views/welcome.blade.php)

何が問題だったのか?

別に記述には問題はありません。問題は、呼び出し側のviewファイルがキャッシュされ、そこにAlertクラスのコンストラクタ周りの情報が残ってしまうからです。ですので、キャッシュが再生成されるようにすれば、問題は解決します。

で、それから?

エラーがドカンと表示されればまだ分かり易いですが、その後例えば、Alertクラスからnameを削除した場合(元に戻した場合)は、少なくとも今回の場合はエラーは表示されません。ですが、キャッシュは、name の指定があるものとして処理しているので、エラーは出なくても、期待した動作では無くなっているかも知れません。(=今回の場合、属性としては取得できていない)

結論

クラスベースのコンポーネントで、コンストラクタ周りをいじった際は、キャッシュがクリアされるようにすると良い、となります。

余談

ちなみに、一応 Issue には報告してみましたが、「キャッシュをクリアしてくれ」という回答でした。

もっとも個人的には、ちょっとしたものは匿名コンポーネントで十分過ぎるので、DBからデータ取ってきたり等しない限りは、匿名コンポーネントを普通に使うと思います。

そう言えば、「Bladeの拡張」を更新した際もキャッシュのクリアが必要でしたね。あまり使わない機能ですが。
ドキュメント:Bladeの拡張

Discussion