Attributes that are collections are not converted to arrays when toArray() method is called on the model.
I discovered this when using collection cast, but it actually applies to all collection attributes.
use Illuminate\Database\Eloquent\Model;
class Dummy extends Model {}
$dummy = new Dummy;
$dummy->foo = collect([1, 2, 3]);
dump($dummy->toArray());
array:1 [
"foo" => array:3 []
]
array:1 [
"foo" => Collection {#602}
]
Adding code below to attributesToArray() method will give expected results.
foreach ($attributes as $key => $value) {
$attributes[$key] = $value instanceof Arrayable ? $value->toArray() : $value;
}
I think attributesToArray() method of the model should check if attribute implements Arrayable interface and then convert it to array with toArray() method.
Please correct me if I am wrong and there is actually a reason for current behavior.
Have you tried casting it to array?
toArray() is recursive for all attributes and relations, so, one way would be to add 'foo' as an attribute.
class Dummy extends Model
{
protected $appends = ['foo'];
public function setFooAttribute($value)
{
$this->foo = $value;
}
public function getFooAttribute()
{
return $this->foo;
}
}
then toArray() will convert 'foo' to an array as well.
Otherwise, you could:
var_dump(json_decode(json_encode($dummy), true));
Thanks for replies!
@Dylan-DPC I want to cast this attribute to collection so casting it to array is kinda counter-productive.
@devcircus I think your code will recurse infinitely - it should be $this->attributes['foo'] instead of $this->foo in both places. Said that it probably solves the issue, however it is almost 10 lines of extra code, with use of functionality that wasn't made for the purpose.
Don't get me wrong, but I didn't add the issue to solve my particular problem, it couldn't be easier after you recognize the cause. I wanted to point out to a behaviour that is probably unexpected by 90% of people especially considering how collections in Laravel do it.
Feel free to open a PR. Closing since it's not actually a bug
Most helpful comment
Thanks for replies!
@Dylan-DPC I want to cast this attribute to collection so casting it to array is kinda counter-productive.
@devcircus I think your code will recurse infinitely - it should be
$this->attributes['foo']instead of$this->fooin both places. Said that it probably solves the issue, however it is almost 10 lines of extra code, with use of functionality that wasn't made for the purpose.Don't get me wrong, but I didn't add the issue to solve my particular problem, it couldn't be easier after you recognize the cause. I wanted to point out to a behaviour that is probably unexpected by 90% of people especially considering how collections in Laravel do it.