0

I have a table with a json column cast as array. The Schema creation has the column defined like this:

$table->json('row_ids');

In my class:

protected $casts = [
    'row_ids' => 'array',
];

I generate the data in this array / column by getting every row id from another table like this:

$id_array = DB::table($table->name)->pluck('api_id')->toArray();

TableChannelRow::create([
    'table_api_id' => $table->api_id,
    'channel_api_id' => $channel->api_id,
    'row_ids' => $id_array,
]);

When I dd a collection record I can see the columns in the target table OK, with one of the columns containing an array as expected:

#attributes: array:4 [▼
  "api_id" => 2
  "table_api_id" => 1
  "channel_api_id" => 6
  "row_ids" => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,  ▶"
]

When I check in MySQLWorkbench the data looks like this:

MySQL Workbench

In another controller I want to add or remove entries from the array in this column like this:

$table_channel_row = TableChannelRow::where('table_api_id', '=', $rowId)
    ->where('channel_api_id', '=', $channelId)
    ->first();

$row_ids = $table_channel_row->row_ids;

if ($is_checked == 'yes') {

    // Add value to array if it does not already exist
    if (!in_array($row_id, $row_ids)) {
        array_push($row_ids, $row_id);
    }

} else {

    // Remove value from array
    $row_id_array[] = $row_id;
    $row_ids = array_diff($row_ids, $row_id_array);

}

$table_channel_row->update([
    'row_ids' => $row_ids,
]);

Now the data in MySQLWorkbench looks like this:

MySQL Workbench

Why does it get stored looking like a PHP array in the first instance, then later on update it gets stored as a json object?

Additionally the remove PHP code is working, yet the add is not, though it does not trigger an exception (you can see the first value is removed in the second image, but I cannot find it in the object in MySQL when I trigger the code to add it)

What did I miss? Thanks!

9
  • I don't believe MySQL has support for Array column. So the `"[1, 2, 3, 4, 5,...]" is invalid. Commented Apr 17, 2019 at 13:55
  • Hmm thanks. Understand. By Laravel is casting the data in this format when I generate the array in the first place this way. Did I mess up how I first generate the data? It seems to use it OK on the second controller Commented Apr 17, 2019 at 13:58
  • @TheRealPapa How did you generate your initial data? Commented Apr 17, 2019 at 14:00
  • When you first created TableChannelRow, you set row_ids to an array, you should have set it to a json encoded version of the array. Commented Apr 17, 2019 at 14:00
  • @Chin Leung hey! Thanks! See the third code snipped above. I pluck the IDs to array then store them in the column, which was created as json. Commented Apr 17, 2019 at 14:01

1 Answer 1

1

The reason why it's saving differently is because array_diff returns an associative array whereas your initial data is an indexed array. Take the following for example:

$ids = [1, 2, 3, 4, 5];
$ids2 = [1, 2, 3];

Then if you perform an array_diff($ids, $ids2), it would return the following:

[
    3 => 4,
    4 => 5
]

So if you want to save as the same format as your initial one, you have to retrieve the values of the array using array_values:

$row_ids = array_values(array_diff($row_ids, $row_id_array));
Sign up to request clarification or add additional context in comments.

6 Comments

You ROCK! Thank you! So now the stored format after removing a value is per first image (PHP array). But why is the push to add the value back not working do you think?
@TheRealPapa Np! What's not working for the push to add?
I cannot see the value added back to the array that is stored in MySQL. Thanks for helping out! I learned quite a bit in the last two nights!
@TheRealPapa Np! Did change back your initial value to ->toArray and was your initial data an indexed aray?
My initial array (stored) was [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,.... After removing id 1 it becomes [2, 3, 4, 5, 6, 7, 8, 9, 10, 11,... but then adding back value 1 (I am using a toggle with AJAX) the array does not contain value 1. Does this answer your q?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.