もはやタイトルの通りなのですが、何度も引っかかるので備忘録としてメモっておきます。
環境
- Laravel6系※5系を利用していたときも同じエラーを踏んだ記憶があります
挙動1:Mailableを継承したクラスでprivateなメンバ変数$messageを持っていると表題のエラーが出る
private $message;
public function __construct(UserDto $userDTO, string $message)
{
$this->userDTO = $userDTO;
$this->message = $message;
}
...中略...
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->subject('タイトル')
->to($this->userDTO)
->view('emails.sample.notified')
->with(['user_name' => $this->userDTO->name, 'message' => $this->message]);
}
まあ、上記のようなメール送信を行うクラスがあったとしましょう。これを利用してメール送信を実行すると
local.ERROR: htmlspecialchars() expects parameter 1 to be string, object given (View: /app/packages/resources/views/emails/sample/notified.blade.php) {"userId":XXXX,"exception":"[object] (ErrorException(code: 0): htmlspecialchars() expects parameter 1 to be string, object given (View: /app/packages/resources/views/emails/sample/notified.blade.php) at /app/packages/vendor/laravel/framework/src/Illuminate/Support/helpers.php:251)
[stacktrace]
というエラーが出ます。
挙動2:$messageをpublicに変えると、何もエラーが出ないがメールも送られなくなる
こちらももっと謎なのですが、
public $message
のように修飾子を変更すると、エラーも出なくなりますがメールも送られなくなります。いよいよ謎です。
対策
withの変数名を変えると動きます。例えばbodyなどに変更します。クラスのmessageプロパティの命名や修飾子は変えなくていいです。
->with(['user_name' => $this->userDTO->name, 'body' => $this->message]);
原因はわからない
追記
コメントの方でこれが原因では、という推測をいただきましたので、原因が気になる方はコメントをご参照ください。
※コメントに至った会話の流れが見えなくなるので、下記記述は一旦消さないでおきます。
軽く追ってみたのですがさっぱりわかりません。ただ、Mailableクラスのここはちょっと怪しいなと感じました。
foreach ((new ReflectionClass($this))->getProperties(ReflectionProperty::IS_PUBLIC) as $property) {
if ($property->getDeclaringClass()->getName() !== self::class) {
$data[$property->getName()] = $property->getValue($this);
}
}
ReflectionClass
を使って自クラスのpublicなプロパティを一覧で取得しており、それを$data
に入れているので、ここで'message'という名前がカニバってしまっており、もともと期待されていた挙動をしなくなったのではないかと類推しました(そこから、挙動2のように修飾子を変える実験に至った)。が、もうちょっと追わないとわからないです。
あと、2020年5月現在のLaravel最新ソースが、僕の手元のソースから若干変更が入っており、現在は治っている可能性は一応あります。
https://github.com/laravel/framework/blob/7.x/src/Illuminate/Mail/Mailable.php
所感
この挙動に基づいたIssueとか見当たらなかったのですが、自社のなんらかの他のソースが影響しているのかなぁ・・・Mailableはそのまま使っているのでありえないとは思うのですが。