jetiradoro/laravel-encrypt-model
Laravel trait to transparently encrypt specified Eloquent model attributes before saving to the database and automatically decrypt them when accessed. Install via Composer, add the Encryptable trait, and list encrypted fields in the $encryptable array.
Installation
Run composer require jetiradoro/laravel-encrypt-model in your project root.
Publish the config (if needed) with php artisan vendor:publish --provider="Jetiradoro\EncryptModel\EncryptModelServiceProvider".
Basic Setup
Add the Encryptable trait to your model and define $encryptable array with field names to encrypt:
use Jetiradoro\EncryptModel\Encryptable;
class User extends Model
{
use Encryptable;
protected $encryptable = ['cc', 'ss', 'phone'];
}
First Use Case Encrypt sensitive data on save:
$user = new User();
$user->cc = '1234567890'; // Automatically encrypted
$user->save();
Retrieve decrypted data:
$user = User::find(1);
$user->cc; // Automatically decrypted
Selective Encryption
Only encrypt specific fields (defined in $encryptable) while leaving others plaintext.
Mass Assignment
Use fill() or create() with encrypted fields:
User::create(['cc' => '1234567890', 'name' => 'John']); // 'cc' encrypted, 'name' plain
Querying Encrypted Fields Avoid querying encrypted fields directly. Use raw queries or decrypt first:
// ❌ Avoid (encrypted values won't match)
User::where('cc', '1234567890')->get();
// ✅ Decrypt first (if needed)
$users = User::all()->filter(fn($u) => decrypt($u->cc) === '1234567890');
API Responses
Use $appends or API resources to control encrypted field exposure:
class User extends Model
{
protected $encryptable = ['cc'];
protected $appends = ['safe_cc'];
public function getSafeCcAttribute()
{
return decrypt($this->cc); // Custom decryption logic
}
}
Form Handling
Use encrypt() helper in controllers/forms:
$request->validate(['cc' => 'required']);
$user->cc = encrypt($request->cc); // Manual override if needed
Migrations
Store encrypted fields as text or longText (default) to avoid truncation:
Schema::create('users', function (Blueprint $table) {
$table->text('cc')->nullable(); // Recommended for encrypted data
});
Testing Mock encryption in tests:
$this->app->instance('encrypt', fn($value) => 'encrypted_' . $value);
toSearchableArray().card_last_four or card_brand if using Stripe.Case Sensitivity
$encryptable must match exactly with column names (including case) in the database.
// ❌ Won't work (case mismatch)
protected $encryptable = ['CC']; // Column is `cc`
Serialization Issues Encrypted fields may break serialization (e.g., Redis, cache). Exclude them:
public function __serialize()
{
return [
'data' => array_except($this->attributesToArray(), $this->encryptable),
'encrypted' => array_only($this->attributesToArray(), $this->encryptable),
];
}
Query Builder Conflicts
Avoid using encrypt() in where clauses:
// ❌ Fails (encrypt() is a helper, not a DB function)
User::whereEncrypt('cc', '1234567890')->get();
Model Events
Encryption runs during saving and retrieved. Override events carefully:
protected static function bootEncryptable()
{
static::saving(function ($model) {
// Custom logic before encryption
});
}
Database Indexes Encrypted fields cannot be indexed for search. Use plaintext fields for indexing.
dd($this->attributes['cc']); // Should show encrypted string
APP_KEY is set in .env (encryption uses Laravel’s default cipher).description). Use text columns for encrypted data.Exclude Sensitive Metadata
Add encrypted fields to $hidden or $visible:
protected $hidden = ['cc', 'ss'];
Custom Encryption
Override the cipher in config/encrypt-model.php:
'cipher' => 'AES-256-CBC',
'key' => env('ENCRYPTION_KEY'), // Custom key
Partial Encryption
Dynamically set $encryptable per instance:
public function setEncryptable(array $fields)
{
$this->encryptable = $fields;
}
Fallback for Older Laravel
If using Laravel < 5.7, manually add the service provider to config/app.php:
'providers' => [
Jetiradoro\EncryptModel\EncryptModelServiceProvider::class,
],
Backup Encryption Key
Store APP_KEY securely. Losing it means permanent data loss for encrypted fields.
How can I help you explore Laravel packages today?