Laravel Eloquent - Encrypting/Decrypt Data on call

eloquent, encryption, laravel, laravel-4

Solution

It doesn't really make sense to encrypt everything. For example, you never want to encrypt the primary key; that doesn't even make sense. Likewise you probably don't want to encrypt the date fields; you'll lose the ability to perform any sort of SQL query on them.

With that in mind, you can try something like this:

class BaseModel extends Eloquent {

    protected $encrypt = [];

    public function setAttribute($key, $value)
    {
        if (in_array($key, $this->encrypt))
        {
            $value = Crypt::encrypt($value);
        }

        return parent::setAttribute($key, $value);
    }

    public function getAttribute($key)
    {
        if (in_array($key, $this->encrypt))
        {
            return Crypt::decrypt($this->attributes[$key]);
        }

        return parent::getAttribute($key);
    }

    public function attributesToArray()
    {
        $attributes = parent::attributesToArray();

        foreach ($attributes as $key => $value)
        {
            if (in_array($key, $this->encrypt))
            {
                $attributes[$key] = Crypt::decrypt($value);
            }
        }

        return $attributes;
    }

}

then have all you models extend this one, and set the `$encrypt` property to whatever columns you want encrypted for that particular model.

P.S. If you want to use Eloquent's accessor functionality, you'll have to play with this a bit more.

Problem

I can use `Crypt` to encrypt/decrypt my data. I want to encrypt some information in my db (such as the name, email, phone number to name a few). Assuming that I want EVERYTHING to be encrypted, I want to be able to do this in the background by itself, which I can perform by overwriting the `create` and `save` functions: ``` // For instance, the save() function could become public function save(array $options = array()) { foreach ($this->attributes as $key => $value) { if (isset($value)) $this->attributes[$key] = Crypt::encrypt($value); } return parent::save($options); } ``` Now, I want the decryption to be performed the same way, so that when I say `User::find($id)`, the returned `$user` is already decrypted. Also other functions such as `firstOrFail()` `get()` `first()` and all to work as well. I also would like this functionality to be extended when I use relationships (so `User::with('someOtherTable')->find($id)` also work). Would this be possible? If this is not possible, I am thinking of creating a helper function `decyrpt()` ``` function decrypt($array) { if (!is_array($array)) return Crypt::decrypt($array); $result = []; foreach($array as $key => $value) $result[$key] = decrypt($value); return $result; } ``` And pass all my results through this first, and then start using them, but it would be nicer if Laravel would provide this, or if there was a "Laravel Way" of doing this.

Original source