Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

RonB1985's avatar

Form request, updating a unique field

I have some validation rules in request classes that have the unique attribute set. Whenever I want to update an existing row in the database, it won't pass, because of this unique attribute.

I've had this issue before, and never was able to get it to work. Tons of topics on the web about this, none of the solutions seem to work. I came up with this:

    public function rules()
    {
        $id = NULL;

        if($this->category)
        {
            $id = $this->category->id;
        }

        return [
            'name' => 'required|alpha_num_spaces|unique:categories,name,' . $id
        ];
    }

I had to do this because when creating a new category, it fails, because the $id (or rather $this->category->id) wasn't set, so I got an error.

The above works. But I hardly think this is the way to go. Any real solution for this?

0 likes
16 replies
kyslik's avatar

Do you have 2 separate requests for creating and updating?

1 like
RachidLaasri's avatar

Try using

'name' => 'required|alpha_num_spaces|unique:categories,name,' . $this->segment(3)
RonB1985's avatar

@RachidLaasri, this feels like a non-solution as well, and segement(3) returns null. Thanks for your answer though!

@kyslik, If you're talking about request forms, I'm using one request form for both creating and updating.

mrabbani's avatar

If your wildcard is category then you should write the following rule:

 'name' => 'required|alpha_num_spaces|unique:categories,name,' .  $this->route('category)
Snapey's avatar

You need to let us know the route to know where to pick up the category ID from.

Is it in the form as a hidden field, or in the query string?

RonB1985's avatar

Im using slugs:

        Route::bind('category', function($value) {
            return Category::where('slug', $value)->firstOrFail();
        });

My routes just look like:

mydomain/categories/slug

The below worked, but same issue when creating a new category, trying to get property of non-object

'name' => 'required|alpha_num_spaces|unique:categories,name,' .  $this->route('category')->id

This doesn't work:

'name' => 'required|alpha_num_spaces|unique:categories,name,' .  $this->route('category')
mrabbani's avatar

One way is:

public function rules() 
{


    $categoryId = null;
 
     if($this->route('category'))
      {  
           $categoryId = App\Category::where('slug', $this->route('category'))->first()->id;
       }

       return [
           'name' => 'required|alpha_num_spaces|unique:categories,name,' . $categoryId
       ];
}

Another way is to ignore a given ID

RonB1985's avatar

Thanks, but the solution I came up with still looks easier and simpler to me, it works. I was just wondering if there was a better way of doing this, like the link you posted, ignoring the ID. But not in the request form I guess :) Thanks though for answering.

        $id = NULL;

        if($this->category)
        {
            $id = $this->category->id;
        }
minjon's avatar

This is the way I establish the validation rules:

class CategoryRequest extends FormRequest
{
    public function rules()
    {
        switch ($this->method())
        {
            case 'POST':
                return [
                    'name' => 'required|unique:categories,name',
                    ];
                    break;

            case 'PATCH':
            case 'PUT':
                return [
                    'name' => 'required|unique:categories,name,' .$this->category->id,
               ];
                break;
        }
    }
}

I hope it will work with you.:)

4 likes
RonB1985's avatar

Thanks, it might work, but I am just not a fan of that method. My own method also worked and is a lot cleaner (for me). I just thought there was a nice laravel-ish way :)

Snapey's avatar

Just be aware that your method works because the id being null seems to cause the unique validation to be broken. Unless its documented that its fine to work in this way, a future version could alter that behaviour?

Is it actually checking for uniqueness?

I'd be tempted to write the rule twice;

    public function rules()
    {
        if($this->category)
        {
        return [
            'name' => 'required|alpha_num_spaces|unique:categories,name,' . $this->category->id
        ];
        }

        return [
            'name' => 'required|alpha_num_spaces|unique:categories'];
    }

2 likes
RonB1985's avatar

Hmm yeah haven't thought of that just yet :) It does work though, when updating an existing field while using the same name, it does update, and when creating a new record with the same name, it throws an error saying a record with that name already exists. So yeah it does work.

But in the end I just thought there would be a nice laravel way for this, but it seems that there is not.

alefcarvalho's avatar

A simple and fast way!

In web.php


Route::post('/companies/update/{company}', 'CompanyController@update');

In CompanyController.php

    
public function update(Company $company, StoreCompanyRequest $request)
{
    //perform your update...
}

In StoreCompanyRequest.php


public function rules()
{

    /*
     * When a company model has been resolved will be ignored by the "unique" rule.
     * The "bypass" variable is automatically converted to the model primary key value.
    */
    $bypass = $this->company->id ?? "";

    return [
          "code"  => "required|digits_between:1,11|unique:companies,code,{$bypass}"
    ];

}

Neeraj1005's avatar

@alefcarvalho you can try also this technique

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class SubcategoryRequest 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 [
            'name' => ($this->getMethod() == 'POST') ? 'required|unique:subcategories|max:50' : 'required|max:50|unique:subcategories,name,'.$this->subcategory->id,
            'category_id' => 'required|not_in:0',
        ];
    }
}

Please or to participate in this conversation.