skip to Main Content

I have a User model that stored credentials as json in db.

class User extends Model
{
    protected $casts = [
        'credentials' => 'array',
    ];
}

$user = User::find(1);
$user->credentials = ['username' => 'john', 'pass' => 'mypass'];
$user->save();

How do I to make the model class cast the pass element of the credentials array?

This doesn’t seem to work:

protected $casts = [
    'credentials' => 'array',
    'credentials->pass' => 'encrypted',
];

3

Answers


  1. Chosen as BEST ANSWER

    So following the @hitesh answer I found the way to do it correctly, which is to use accessors and mutators and remove array casting from the model and use json_decode and json_encode for the value in the accessor and the mutator respectively, otherwise there'll be an error with array casting.

    class User extends Model
    {
        public function getCredentialsAttribute(string $value): array
        {
            $value = json_decode($value, true);
    
            if (isset($value['pass'])) {
                $value['pass'] = decrypt($value['pass']);
            }
    
            return $value;
        }
    
        public function setCredentialsAttribute(array $value): void
        {
            if (isset($value['pass'])) {
                $value['pass'] = encrypt($value['pass']);
            }
    
            $this->attributes['credentials'] = json_encode($value);
        }
    }
    

  2. Laravel as of now (10.x) doesn’t support this type of casting. For now you can only use "->" in updating nested keys.

    $user = User::find(1);
     
    $user->update(['credentials->pass' => 'mypass']);
    

    You can read more in the official documentation regarding array casting.

    If you really need to cast nested values you will have to define your own attribute accessors/mutators for ‘credentials’ and do all the transformations yourself.

    Login or Signup to reply.
  3. As mentioned @d3jn in the answer, It was better to add the accessors/mutators. Please check below whole User model code.

    class User extends Model
    {
        protected $casts = [
            'credentials' => 'array',
        ];
    
        public function getCredentialsAttribute($value)
        {
            if(isset($value['pass'])) {
                $value['pass'] = decrypt($value['pass']);
            }
            return $value;
        }
    
        public function setCredentialsAttribute($value)
        {
            if(isset($value['pass'])) {
                $value['pass'] = encrypt($value['pass']);
            }
            $this->attributes['credentials'] = $value;
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search