Eloquent casts on a JSON column, and the mutation that does not save

An array cast decodes on read and encodes on write, and modifying the decoded array in place does not mark the attribute as dirty — so the save writes nothing.

// does not save
$order->options['gift_wrap'] = true;
$order->save();

// works
$options = $order->options;
$options['gift_wrap'] = true;
$order->options = $options;
$order->save();

// or, on a JSON column, let MySQL do it
DB::table('orders')->where('id', $id)
    ->update(['options->gift_wrap' => true]);

The first version does not even produce an error — it modifies a temporary array returned by the accessor and discards it. That silence is what makes this a recurring bug rather than a one-time lesson. The arrow syntax in the query builder writes into the JSON document server-side, which avoids reading and rewriting the whole column and is safe against a concurrent update to a different key.