Laravelでメール送信処理を実装している際に、Mailableのコンストラクタで定義したpublicプロパティから渡しているつもりの値と異なる値が、テンプレート側から参照されていることに気づき、原因を調べたところ、Laravelの標準メール機能にある自動データインジェクションが影響していました。
Mailableでpublicプロパティを持たせてコンストラクタから値を渡す構成にしていたところ
class SampleMail extends Mailable
{
public function __construct(
public string $subjectText,
) {}
public function build()
{
return $this->subject($this->subjectText);
}
}
subject()に渡される$subjectTextの値が想定と異なるものになり
メールタイトルが意図しない内容になっていました。
原因: 自動データインジェクション
LaravelのMailableクラスは、メールテンプレート(Blade)に渡すデータを用意する際に、
Mailableクラス内のpublicプロパティと、with()などで指定したデータをまとめて配列にしてビューに渡します。
このとき同じ名前のキーが存在すると「あとから渡された値」が有効になるため、
結果として、意図しない値がビューへ渡されてしまい、上書きされたように見えることがあります。
解決方法: public → protected へ変更
テンプレート側へ公開したくない値は、
アクセス修飾子をprotectedまたはprivateに変更するのが安全です。
class SampleMail extends Mailable
{
public function __construct(
protected string $subjectText,
) {}
public function build()
{
return $this->subject($this->subjectText);
}
}
この変更により自動インジェクションの対象から外れるためビューに渡される値の競合を避けられます。
まとめ
発生した問題:
Mailableのpublicプロパティと同名のキーが他のデータと競合してテンプレートから参照される値が意図せず変わる
原因:
自動データインジェクションによるビュー用データのマージ
解決方法:
publicをprotected or privateに変更
学び:
なんでもかんでもpublicはキケン