0

I am having a problem saving one of my models from a different model. The model in question is my Job model, and the model I am trying to save is my SatusBar model. Within the statusBar model, I have a json database field called fields. In my StatusBar model, I have:

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

public function status()
{
  return $this->morphTo();
}

In my Jobs controller, where I am trying to update the fields json, I have tried saving it twice:

public function updateStatus(Request $request, Job $job){

$id = $job->status['id'];
$fields = $job->status['fields'];

$id = $job->status['id'];
$fields = $job->status['fields'];
$save = false;

foreach($fields as &$field){
  if($field['field'] == $changeField){
    foreach($field['options'] as $opt){
      if($opt['slug'] == $status){
        $field['selected'] = $status;
        $save = true;
        break 2;
      }
    }
  }
}


if($save){
  //This way works as expected, but doesn't look pretty
  $s = StatusBar::find($id);
  $s->fields = $fields;
  $s->save();

  //This results in an array to string conversion error
  //$job->status()->update(['fields' => $fields]);
}

Why does the second part of the save method result in an array to string conversion error?

1

1 Answer 1

1

The latter (calling status()->update(...)) won't work because attribute casting is not called on query builder instances and by using the relation as a method call you are silently obtaining the underlying query builder object of your eloquent query builder that you started with from the Model.

The query builder doesn't have the concept of Models, so it won't look for any attribute cast, as a result the fields value will be put like that in the sql query string and this process causes the Array to string conversion.

Update
I think the only way you can avoid that error is to directly encode the value yourself:

$job->status()->update(['fields' => json_encode($fields)]);

This is what is actually done under the hood by laravel when you set an attribute cast of array on a field to encode it back before database saving, but keep in mind that this method is error-prone because you could someday change the mutator on that field and forget about this big.

I will further look in the source code and update this answer if I find anything that might be suited to this use case.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the explanation. Is there a way to get this method to work with some sort of mutator? laravel.com/docs/5.8/eloquent-mutators#accessors-and-mutators
This works! Not sure why I didn't think of this before. I guess I was trying to dig deeper into other things rather than the simple approach of just encoding it directly. Thanks!

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.