Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Kryptonit3's avatar

Database stored JSON not casting to PHP array

Laravel version: 5.6.18

Database Scema

        Schema::create('twilio_users', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('created_by')->unsigned();
            $table->foreign('created_by')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
            $table->integer('updated_by')->unsigned()->nullable();
            $table->foreign('updated_by')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
            $table->string('name');
            $table->string('number');
            $table->string('extension')->nullable();
            $table->json('availability');
            $table->boolean('calls_enabled')->default(true);
            $table->boolean('dial_by_extension_enabled')->default(true)->nullable();
            $table->timestamps();
        });

TwilioUser Model

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class TwilioUser extends Model
{
    protected $casts = [
        'availability' => 'array',
    ];
}

TwilioUserTableSeeder.php

<?php

use Illuminate\Database\Seeder;

use App\User;
use App\TwilioUser;

class TwilioUserTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $created = User::first();
        $json = File::get('database/seeds/data/twilio_user_table_seed.json');
        $user = new TwilioUser();
        $user->created_by = $created->id;
        $user->name = 'User Name';
        $user->number = '+15025551234';
        $user->extension = '701';
        $user->calls_enabled = true;
        $user->dial_by_extension_enabled = true;
        $user->availability = $json;
        $user->save();
    }
}

\database\seeds\data\twilio_user_table_seed.json

{"sunday":{"enabled":true,"start":"09:00:00","end":"17:00:00"},"monday":{"enabled":true,"start":"09:00:00","end":"17:00:00"},"tuesday":{"enabled":true,"start":"09:00:00","end":"17:00:00"},"wednesday":{"enabled":true,"start":"09:00:00","end":"17:00:00"},"thursday":{"enabled":true,"start":"09:00:00","end":"17:00:00"},"friday":{"enabled":true,"start":"09:00:00","end":"17:00:00"},"saturday":{"enabled":true,"start":"09:00:00","end":"17:00:00"}}

php artisan tinker output depicting issue

>>> $user = TwilioUser::first();
=> App\TwilioUser {#2384
     id: 1,
     created_by: 1,
     updated_by: null,
     name: "User Name",
     number: "+15025551234",
     extension: "701",
     availability: ""{\"sunday\":{\"enabled\":true,\"start\":\"09:00:00\",\"end\":\"17:00:00\"},\"monday\":{\"enabled\":true,\"start\":\"09:00:00\",\"end\":\"17:00:00\"},\"tuesday\":{\"enabled\":true,\"start\":\"09:00:00\",\"end\":\"17:00:00\"},\"wednesday\":{\"enabled\":true,\"start\":\"09:00:00\",\"end\":\"17:00:00\"},\"thursday\":{\"enabled\":true,\"start\":\"09:00:00\",\"end\":\"17:00:00\"},\"friday\":{\"enabled\":true,\"start\":\"09:00:00\",\"end\":\"17:00:00\"},\"saturday\":{\"enabled\":true,\"start\":\"09:00:00\",\"end\":\"17:00:00\"}}"",
     calls_enabled: 1,
     dial_by_extension_enabled: 1,
     created_at: "2018-04-30 16:40:39",
     updated_at: "2018-04-30 16:40:39",
   }
>>> $availability = $user->availability;
=> "{"sunday":{"enabled":true,"start":"09:00:00","end":"17:00:00"},"monday":{"enabled":true,"start":"09:00:00","end":"17:00:00"},"tuesday":{"enabled":true,"start":"09:00:00","end":"17:00:00"},"wednesday":{"enabled":true,"start":"09:00:00","end":"17:00:00"},"thursday":{"enabled":true,"start":"09:00:00","end":"17:00:00"},"friday":{"enabled":true,"start":"09:00:00","end":"17:00:00"},"saturday":{"enabled":true,"start":"09:00:00","end":"17:00:00"}}"
>>> $availability->sunday
PHP Notice:  Trying to get property 'sunday' of non-object in Psy Shell code on line 1
>>> $availability['sunday']
PHP Warning:  Illegal string offset 'sunday' in Psy Shell code on line 1
>>>

Am I missing something? I may not be understanding the whole "Casting" thing. Was really hoping to be able to use the auto translate between the database and the code instead of having to perform encode and decodes.

Thanks in advance.

0 likes
8 replies
Cronix's avatar

You can't directly cast json to an array like that. You have to json_decode() it first.

You could create an accessor and json_decode() it there, and a mutator to change it back to json when storing by using json_encode().

public function getAvailabilityAttribute($value)
{
    return json_decode($value); // or json_decode($value, true) for associative array
}

public function setAvailabilityAttribute($value)
{
        $this->attributes['availability'] = json_encode($value);
}

Now when you retrieve a model, when accessing the availability property, it should be a php array. When you save it, it will convert it back to json.

https://laravel.com/docs/5.6/eloquent-mutators#accessors-and-mutators

Kryptonit3's avatar

@Cronix yeah, I knew I could get and set. My example shows me retrieving a model and attempting to access the availability property. Right? O.o

Cronix's avatar

Interesting. The json type isn't in the docs. Yeah, try json datatype. You'll note it's doing exactly what I did in my accessor example.

The $casts property on your model provides a convenient method of converting attributes to common data types. The $casts property should be an array where the key is the name of the attribute being cast and the value is the type you wish to cast the column to. The supported cast types are: integer, real, float, double, string, boolean, object, array, collection, date, datetime, and timestamp.

https://laravel.com/docs/5.6/eloquent-mutators#attribute-casting

Kryptonit3's avatar

Tried all three types, json, object, array and dd($user->availability) never changes.

Am I accessing the data improperly to invoke the casting?

Kryptonit3's avatar
Kryptonit3
OP
Best Answer
Level 11

Figured it out. Data going into the model is expected to be an array, not already json. In my seed file I changed the line $user->availability = $json; to $user->availabilty = json_decode($json, true); so the Model would receive what it was looking for... a php array. Now php artisan tinker shows good data.

>>> $user = TwilioUser::first();
[!] Aliasing 'TwilioUser' to 'App\TwilioUser' for this Tinker session.
=> App\TwilioUser {#2394
     id: 1,
     created_by: 1,
     updated_by: null,
     name: "User Name",
     number: "+15025551234",
     extension: "701",
     availability: "{"friday": {"end": "17:00:00", "start": "09:00:00", "enabled": true}, "monday": {"end": "17:00:00", "start": "09:00:00", "enabled": true}, "sunday": {"end": "17:00:00", "start": "09:00:00", "enabled": true}, "tuesday": {"end": "17:00:00", "start": "09:00:00", "enabled": true}, "saturday": {"end": "17:00:00", "start": "09:00:00", "enabled": true}, "thursday": {"end": "17:00:00", "start": "09:00:00", "enabled": true}, "wednesday": {"end": "17:00:00", "start": "09:00:00", "enabled": true}}",
     calls_enabled: 1,
     dial_by_extension_enabled: 1,
     created_at: "2018-04-30 18:32:13",
     updated_at: "2018-04-30 18:32:13",
   }
>>> $user->availability
=> [
     "friday" => [
       "end" => "17:00:00",
       "start" => "09:00:00",
       "enabled" => true,
     ],
     "monday" => [
       "end" => "17:00:00",
       "start" => "09:00:00",
       "enabled" => true,
     ],
     "sunday" => [
       "end" => "17:00:00",
       "start" => "09:00:00",
       "enabled" => true,
     ],
     "tuesday" => [
       "end" => "17:00:00",
       "start" => "09:00:00",
       "enabled" => true,
     ],
     "saturday" => [
       "end" => "17:00:00",
       "start" => "09:00:00",
       "enabled" => true,
     ],
     "thursday" => [
       "end" => "17:00:00",
       "start" => "09:00:00",
       "enabled" => true,
     ],
     "wednesday" => [
       "end" => "17:00:00",
       "start" => "09:00:00",
       "enabled" => true,
     ],
   ]
Cronix's avatar

Using the mutator that I showed, setAvailabilityAttribute(), would do that too. You give it an array, and when you save the model it automatically converts it to json.

Please or to participate in this conversation.