Laravel 新コンポーネントのちょっとした注意点
前置き
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