I came across this issue too.
My solution is to use Laravel Scout to build a search index.
Depending on the security policies of the encrypted data (and the search driver you're using), this solution may not be suitable.
I am using the Laravel TNT Search Driver which stores the index on my server.
<?php
namespace App\Models;
use Illuminate\Support\Facades\Crypt;
use Laravel\Scout\Searchable;
class User extends Model
{
use Searchable;
public function toSearchableArray(): array
{
return [
'id' => $this->id,
'email' => $this->getDecryptedEmail()
];
}
public function getDecryptedEmail(): string
{
return Crypt::decryptString($this->email);
}
}
Then in your controller, or wherever you want to implement the search function:
...
public function search(Request $request)
{
return User::search($request->input('email'))->get();
}
...
If you need to do an exact match, you can use the filter
method on the search results. Doing the search first should provide better performance rather than filtering large sets of data.
You can also place constraints on the search function if you need to, for example:
public function search(Request $request)
{
$constraints = User::where('is_active', '=', 1);
$filtered = User::search($request->input('email'))
->constrain($constraints)
->get()
->filter(function ($user) use ($request) {
return $user->getDecryptedEmail() === $request->input('email');
});
}