Laravel の Model で配列に cast させる際に文字化けさせないようにする
日本語のエラーメッセージなどを扱う際に、PHP の json_encode
を使用する場合には、第二引数に JSON_UNESCAPED_UNICODE
を指定する必要があります。
<?php php > echo json_encode(['あ', 'い']); ["\u3042","\u3044"] php > echo json_encode(['あ', 'い'], JSON_UNESCAPED_UNICODE); ["あ","い"]
定義済み定数の詳細についてはこちら
Model の $cast で array を指定する場合
日本語をそのまま保存しようとする場合には同様の対応が必要になります。これも内部的には保存時に json_encode を実行していて、取得時に json_decode を実行するようになるからです。
User クラスは適当なのであしからず。
<?php >>> factory(App\Models\User::class)->create(['some_list' => ['あ', 'い']]) => App\Models\User {#4716 some_list: "["\u3042","\u3044"]", updated_at: "2021-08-02 14:47:01", created_at: "2021-08-02 14:47:01", id: 191, }
これは Medel 内で asJson を指定して、下記のようにすることで保存できるようになる。
都度定義するのは手間なので、親クラス側で定義しても良いかと思う。
<?php class User extends Model { // 省略 protected $casts = [ 'some_list' => 'array', ]; // Model 内にこれを指定 protected function asJson($value) { return json_encode($value, JSON_UNESCAPED_UNICODE); } } // 再度 tinker から検証 >>> factory(App\Models\User::class)->create(['some_list' => ['あ', 'い']]) => App\Models\User {#3785 some_list: "["あ", "い"]", updated_at: "2021-08-02 14:47:38", created_at: "2021-08-02 14:47:38", id: 192, }
Collectionでも同様
ちなみに、collection の toJson も同様です。内部で json_encode を実行しているだけなので引数に JSON_UNESCAPED_UNICODE
を指定する必要があります。
<?php >>> User::first()->toJson() => "{"id":1,"name":"\u3042","created_at":"2021-07-21 10:09:53","updated_at":"2021-07-21 10:09:53"}" >>> User::first()->toJson(JSON_UNESCAPED_UNICODE) => "{"id":1,"name":"あ","created_at":"2021-07-21 10:09:53","updated_at":"2021-07-21 10:09:53"}"