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

jrdavidson's avatar

Unique Rule after Validation

I am currently trying to validate two fields in my form that one is a string and the other is a number. I can get both of these to pass, however, the next validation I need to take place is to check to make sure the two fields concatenated together doesn't already exist in a database table. I have included the rules below

My first thought is to do a after validation hook and query the db to see if the model exists with that concatenated name but didn't know if there was a better way of handling this situation.

public function rules()
{
    return [
        'term' => ['required', 'string', Rule::in(['Spring', 'Summer', 'Fall'])],
        'year' => ['required', 'numeric', 'digits:4'],
    ];
}
0 likes
10 replies
jrdavidson's avatar

I think you did. I need to figure out that as long both the term and year fields pass then con are are both their values and then do database query to make sure that the concatenated string doesn’t match another column in the database.

prospero's avatar

Do you have a column in db to store the concatenated string? This can avoid make different queries in joining the results for validation...it's just an idea. In this way you only need to add another property for the concatenated field and pass it to the validation rule

jrdavidson's avatar

I don’t understand what you are saying. I have a column in the database called (name). After term and year are validated I want to concat them together and make sure that the concatenated string doesn’t match a column value for (name).

prospero's avatar

Ah ok. You already have a column to match with the concatenated string...don't get that, sorry. I don't know about a useful method for that, so I made it on hand including in rules a property with the concatenated string like

$this->concatString = $this->term.'-'.$this->year;
...
public function rules()
{
    ... 
    'concatString' => ['unique:tableName'] 
}

Of course you must have a "name" property, and you must handle that sensitive case.

chaudigv's avatar
chaudigv
Best Answer
Level 16

If you would like to add an "after" validation hook to a form request, you may use the withValidator method. This method receives the fully constructed validator, allowing you to call any of its methods before the validation rules are actually evaluated:

public function withValidator($validator)
{
    $validator->after(function ($validator) {
        $concatenatedName = request('term') . request('year');
        
        if(User::where('name', $concatenatedName)->exists()) {
            $validator->errors()->add('field', 'Something is wrong with this field!');
        }
    });
}
2 likes
Snapey's avatar

You can use a form request and add a prepareForValidation method. In this method set the concatenated value and then validate that the concatenated value is unique in the database.

protected function prepareForValidation()
{
    $this->merge([
        'name' => request('term') . request('year'),
    ]);
}

and then add 'name' to your rules and check its uniqueness

1 like
jrdavidson's avatar

How can I make sure that the individual fields themselves validate successfully before it hits the concatenated validated?

teos_97's avatar

in addition to what @chaudigv said, you could check :

public function withValidator($validator)
    {
        if (!$validator->fails())
        {
		 //Validate only your concatinated field manually as per @chaudigv  answer or make a new validator
		    $data = ['name' => request('term') . request('year')]
            $newValidator = Validator::make($data, [
                'name' => ['unique:tableName,columnName']
            ]);
            $newValidator->validate();
        }
    }

I'd probably do this manually again as @chaudigv suggested as I assume you do not have an input field 'name' on your form, so if the validator fails it won't show the error and you'd have to manually add it to the errorbag. Haven't run the code but it should give you an idea, hope this helps.

Snapey's avatar

or, throw a validation exception after checking the other fields.

use Illuminate\Validation\ValidationException;

if (MyModel::where('name',$request->term . $request->year)->exists() {
    throw ValidationException::withMessages(['term' => 'We already have a record for this term+year']);
}
2 likes

Please or to participate in this conversation.