3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Laravelでメールを送るときに$messageという変数を使ったら「htmlspecialchars() expects parameter 1 to be string, object given」というエラーが出る

Last updated at Posted at 2020-05-30

もはやタイトルの通りなのですが、何度も引っかかるので備忘録としてメモっておきます。

環境

  • 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クラスのここはちょっと怪しいなと感じました。

Mailable.phpL297
        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はそのまま使っているのでありえないとは思うのですが。

3
1
1

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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?