Laravel-mongodb: array filed saved as string

Created on 18 Oct 2016  路  4Comments  路  Source: jenssegers/laravel-mongodb

Hi there,
When I try creating new instance with Jenssegers\Mongodb\Eloquent\Model as shown below, metadata field saved as string (json encoded).

Should I do it in a different way?

$log = new Log();
$log->fill([
    'creator_id' => 5,
    'metadata'   => ['content' => 'HHHHH'],
]);

$log->save();

Then the saved data looks like this:

{ 
    "_id" : ObjectId("5805f08476d2cd3d474a8133"), 
    "creator_id" : 5, 
    "metadata" : "{\"content\":\"HHHHH\"}"
 }

What I except is:

{ 
    "_id" : ObjectId("5805f08476d2cd3d474a8133"), 
    "creator_id" : 5, 
    "metadata" : {"content":"HHHHH"}
 }

Most helpful comment

After digging into Eloquent's code a bit more, found this little helpful tidbit in Eloquent/Concerns/HasAttributes.php:

// Next we will handle any casts that have been setup for this model and cast
// the values to their appropriate type. If the attribute has a mutator we
// will not perform the cast on those attributes to avoid any confusion.

Thus, adding a "do nothing" mutator solved the storage format issue in this case:

public function setSourcesAttribute($value) {
   $this->attributes['sources'] = $value;
}

In the end, we have "sources" : [ "test1234" ] in the datastore as expected.

All 4 comments

There is no idea about it?!

I can confirm this situation.

I have a Model with a "sources" attribute which is cast as an array. I can fill and manipulate the Model, all the while, "sources" is treated as an array.

However, when saving the Model, it is actually stored as "sources" : "[\"abcd124\"]",. It should be stored as "sources" : ["abcd1234"].

Yes, when retrieving the data from the datastore, the Model converts the "[\"abcd1234\"]" string value into an array for the Model instance, but it is stored in a non-conforming manner and is thus not accessible to other tools/etc which expect that document attribute to be an array.

What is the proper method to use to force it to store native structures?

After digging into Eloquent's code a bit more, found this little helpful tidbit in Eloquent/Concerns/HasAttributes.php:

// Next we will handle any casts that have been setup for this model and cast
// the values to their appropriate type. If the attribute has a mutator we
// will not perform the cast on those attributes to avoid any confusion.

Thus, adding a "do nothing" mutator solved the storage format issue in this case:

public function setSourcesAttribute($value) {
   $this->attributes['sources'] = $value;
}

In the end, we have "sources" : [ "test1234" ] in the datastore as expected.

thanks you @kodekrash

Add below lines in model file for setting all attribute as per type casts

public function setAttribute($key, $value) {
    $this->attributes[$key] = $value;
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

kschethan picture kschethan  路  3Comments

yupangestu picture yupangestu  路  3Comments

ricardofontanelli picture ricardofontanelli  路  3Comments

sanjay1688 picture sanjay1688  路  3Comments

BlakeGardner picture BlakeGardner  路  3Comments