archtechx / virtualcolumn

Eloquent Virtual Column package.
MIT License
72 stars 12 forks source link

Add encrypted casts support + allow using the trait on multiple models #14

Closed lukinovec closed 1 year ago

lukinovec commented 1 year ago

Encrypted casts

This PR adds support for encrypted casts. Laravel's default encrypted casts ('encrypted', 'encrypted:array', 'encrypted:collection', 'encrypted:json', 'encrypted:object') work out of the box, but the custom casts have to be specified in VirtualColumn::$customEncryptedCastables.

The problem with encrypted casts is that VirtualColumn uses $model->setAttribute(), and when using the encrypted casts, the password gets encrypted multiple times in the end. To deal with that, we check if the value is encrypted. If it is, use $model->attributes[$key] = $value instead of $model->setAttribute($key, $value) to bypass the encryption.

Shared state issues

When multiple models extended a base class that used VirtualColumn, there were issues with the shared state. Booting the trait would add event listeners specific to the model the trait's used on to the static $afterListeners property. The problem is that this was happening with each used model, and in the end, the models initialized after the first one wouldn't handle the events properly. For example, creating an instance of model Bar after creating Foo would result in Bar getting encoded using the same custom columns as Foo because Foo got initialized first.

In this PR, most of the static things in the VirtualColumn trait got changed to non-static, so that the state isn't shared across models.