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

lpel's avatar
Level 1

Trouble accessing and modifying JSON data with Eloquent in Laravel 8

Only a few moments ago, my code worked as intended, then I called php artisan migrate:fresh to clear out my database and things stopped working.

All I want to do is to retrieve properties from my JSON column, and then update it. But whenever i try to retrieve the value, it says

ErrorException Illegal string offset 'starred'

This is my code:

inventory.php

protected $guarded = [];

protected $casts = [
    'extra' => 'array'
];

InventoryController.php

public function visible($code) {
    $inventory = Inventory::where('code', $code)->firstOrFail();

    if ($inventory->extra['starred'] === true) {
        $inventory->update([
            'extra->starred' => false
        ]);
    } else {
        $inventory->update([
            'extra->starred' => true
        ]);
    }

    return $inventory;
}

Any clue to whatever is going on here would be much appreciated! It was working as intended not too long ago, but now - it's not. This is called through an API.

0 likes
8 replies
Nakov's avatar

Have you tried casting to json instead?

protected $casts = [
    'extra' => 'json'
];
lpel's avatar
Level 1

@Nakov I tried both as JSON and array and neither worked, sadly.

The issue arises whenever I call 'starred', whether to read from it, or in the update function. This property DOES already exist in the JSON object as well.

Nakov's avatar

@lpel yeah, for you it fails here I guess

 if($inventory->extra['starred'] === true)

What do you get if before the condition you check?

dd( $inventory->extra);

is it an array, and does it contain the key?

lpel's avatar
Level 1

@Nakov

"{"purchaseLimit":"","priority":"5","starred":false,"visible":true,"discount":false}"

I get this. I can retrieve the value if I use json_decode, but then comes the issue of updating the value. It gives the same error in that line. I've seen examples of code online that doesn't use json_decode - and it worked pretty normal before using php artisan migrate:fresh. So It's a really confusing situation.

Nakov's avatar

@lpel well, but you cannot try to access a key on a string, as that's what you got there. That's why I said you need to cast it to json or try updating like this

https://laravel.com/docs/8.x/eloquent-mutators

And stop the saying it worked and now it does not, because clearly something changed in the meantime. Either the data is different, or it was stored differently, or you introduced some new code in between.

I guess you don't have tests, so you cannot prove exactly the same code used to work, and suddenly it decided nah, I am not gonna work anymore.

  • Edit

When you store the data initially do you use json_encode? If you do, then remove that. Because clearly for you the casting does not work, based on the response you get when you use dd().

lpel's avatar
Level 1

@Nakov

I currently have it set to cast to json and it gives the same error. I tried swapping out the two to see if it changed anything, but it didn't.

No, I wasn't doing any unit testing, and so I can't prove it - but I ctrl + Z'd to every other instance of code (not the best metric, I know) to no change. The change came AFTER I dropped all tables and redid the migrations. The data going in doesn't seem to affect the output. I tried to recreate the exact example used on that page concerning casting, and the same issue arises. The JSON column is still named 'extra' in the migrations.

Which is why I'm confused. My syntax appears to match how it's supposed to be done. I know it worked pre-migration - but even if that was a hallucination, I don't see why it shouldn't work if I try to recreate a simple example on updating JSON columns.

Also no, i didn't use json_encode. I tried storing the data both through my front-end with a HTTP request with Axios (I tried both using JSON.stringify() and without it to see if it made a difference), and I also used Insomnia to input the data as well to see if that made a difference.

Edit

Even if I do get beyond that first conditional statement using json_decode, it throws the same error at

         $inventory->update([
            'extra->visible' => false
        ]);

I recall clearly that the first time, I tried using updateOrCreate, and it threw and error, then I removed the 'OrCreate', and it worked. But this time, it consistently tells me that I'm using an illegal string offset.

automica's avatar

@lpel as you’ve mentioned above you don’t have a test for this, the most obvious next step is write one.

With a test in place, you will have a reliable repeatable way of validating the your method works (or doesn’t work) and then you can tweak the method you are testing until you test passes.

Without tests you can find yourself changing multiple things at a time which impede your development.

Approach writing tests as a means of scaffolding your methods. This scaffolding will help you define your expectations, and ensures code still works when you build out additional functionality and refactor.

Please or to participate in this conversation.