Liglo App
Liglo App

Reputation: 3819

Cake 3: column of type JSON stores a NULL as string "null"

My model is defined as follows:

<?php
namespace App\Model\Table;

use Cake\ORM\Table;
use Cake\Database\Schema\Table as Schema;

class AppLogsTable extends Table
{    
    protected function _initializeSchema(Schema $schema) {
        $schema->columnType('data', 'json');
        return $schema;
    }       
}

The JSON format is correctly applied when saving into database and when retrieving data. However, if I set $appLog->data = null and save it through $this->appLogs->save($appLog) it would save a string null into the database rather than a real NULL value. The colum data in the app_logs table is set to accept nulls.

If I uncomment the column type definition, it stores nulls correctly.

How to keep the automatic JSON data type and store NULL correctly from the model?

Upvotes: 4

Views: 1124

Answers (1)

ndm
ndm

Reputation: 60453

You'll have to use a custom/extended database type class that handles null values accordingly, the built-in one will pass everything through json_encode() no matter what.

Something along the lines of this:

// src/Database/Type/NullAwareJsonType.php

namespace App\Database\Type;

use Cake\Database\Driver;
use Cake\Database\Type\JsonType;

class NullAwareJsonType extends JsonType
{
    public function toDatabase($value, Driver $driver)
    {
        if ($value === null) {
            return null;
        }

        return parent::toDatabase($value, $driver);
    }
}

You can then either override the built in json type:

// config/bootstrap.php

\Cake\Database\Type::map('json', \App\Database\Type\NullAwareJsonType::class);

or map it as a new type and set the column type accordingly:

\Cake\Database\Type::map('nullAwareJson', \App\Database\Type\NullAwareJsonType::class);
$schema->columnType('data', 'nullAwareJson');

See also

Upvotes: 3

Related Questions