0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Laravel】なんでもpublicにすると危険:Mailableで遭遇した値競合トラブル

Posted at

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はキケン

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?