【Laravel】not null 制約をつけた json 型カラムから読んだ値が null になるパターンの紹介

 題の通りです。これは MySQL の値としての null と JSON としての null の二種類が存在すること、Laravelに自動で JSON をでコードするようにできる機能があることの二つが原因で起きる現象です。

 まず MySQL の not null 制約の中で JSON としての null を格納する方法を説明します。これの具体例として次があげられます。

-- auto-generated definition
create table jsons
(
    json_data json not null,
    json_nullable json
);
insert into jsons(json_data) values('null'); -- JSONとして解釈できる null と null そのものを格納
insert into jsons(json_data, json_nullable) values('{"a": 1}', '{"b": 2}'); -- nullでないJSONの例
 
select * from jsons;
-- json_data	json_nullable
-- null	NULL
-- {"a": 1}	{"b": 2}

 ’null’を保存できます。これは null を JSON としてエンコードした際に得られる文字列であり、MySQL は JSON があるので null でないとして”null”を保存します。

 また Laravel の Eloquent にはキャストという機能があり、これはデータベースの特定のカラムから値を読み取る時、自動で型変換をする機能です。これを JSON 型にかけると次の様になります。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Json extends Model
{
    public $table = 'jsons';


    protected $casts = [
        'json_data' => 'json',
    ];
}

// どこかで
$res=\App\Models\Json::query()->first()->toArray();
dd($res);
// array:3 [▼
//   "json_data" => null
//   "json_nullable" => null
// ]

 このキャスト機能の json 指定では自動で JSON をパースし、パース結果の値をプロパティにできます。これを先ほどの null を元にした Json の値をパースした所 null が返ってきました。not null 制約が付いたカラムの値が null を返してきたわけです。

 どちらも便利な機能ですが、組み合わせると厄介な性質が現れます。うまいことバリデーションなりなんなりで対処して、そもそも JSON としての null も保存できない様にした方が無難です。

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG