If you have been using soft delete in your application then you may have come across this situation. When we try to create a new record with the same value for a unique field name, it throws an exception for duplicate records. It’s quite common. In this article, we will learn how we can handle this error efficiently in Laravel.
Here, we will be testing it with users
table for email
column. First of all, we need to remove unique()
constraint from the column.
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email'); // <-- remove unique() from this column
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
Refresh the migration to generate the modified table.
php artisan migrate:fresh
Now, we need to create a form request to write our validation logic. Run below command to create a new form request for users
table.
php artisan make:request UserRequest
This will generate a UserRequest.php
file inside app/Http/Requests/
directory. Our main goal is to customize the unique field validation for email. I will add validation logic which looks like below.
<?php
namespace App\Http\Requests;
use Illuminate\Validation\Rule; //<-- import this class
use Illuminate\Foundation\Http\FormRequest;
class UserRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
..........
'email' => 'required', Rule::unique('users')->whereNull('deleted_at')
..........
];
}
}
In the above code, we use Rule
class with a unique method which accepts table name i.e. users
in our case. Then, we check the condition where deleted_at
column is null.
We can also use withoutTrashed
method instead of whereNull
. Thus, our validation looks like below.
..............
public function rules()
{
return [
..........
'email' => 'required', Rule::unique('users')->withourTrashed('deleted_at')
..........
];
}
This is pretty straightforward. What are your thoughts? Don’t forget to drop your comments below.