0

I want to create a Form Request validation and don't know how-to.

I have a form:

<form>
  <input type="text" name="fullname[0]">
  <input type="text" name="document_num[0]">

  <input type="text" name="fullname[1]">
  <input type="text" name="document_num[1]">

  <input type="text" name="fullname[2]">
  <input type="text" name="document_num[2]">

   .....

  <input type="text" name="fullname[n]">
  <input type="text" name="document_num[n]">

  <input type="submit">
</form>

table 'users':

  id | fullname | document_num
  1  | John     | 111
  2  | Jane     | 112
 ..  | ...      | ...

when user clicks submit a request is sent to controller method where it’s first being validated by Form Request (or it can be a regular Validator). So I want to write a rule which checks:

for (i=0; i<numberOfUsersToAdd; i++)

    if  (‘document_num[$i]’ exists in ‘users’ in field ‘document_num’ ) {

       $user = Users::find(id of user in DB having this ‘document_num[$i]’) ; 

       check if (fullname[$i] == $user->fullname) {

                return true} // input-ed users name match his/her name in DB.

        else {return false}  // input-ed users name doesn't match his/her name in DB.

        } 

    else return true; // document_num[$i] doesn't exists in the database which's ok

if in words: check if any input-ed document_num[$i] exists in the table users, if yes, get the user having this document_nubmer from DB and compare his/her fullname value to fullname[$i] from input.

How to do it?:)

Appreciate any help!:)

2
  • What version of Laravel are you using? Commented Jul 3, 2017 at 13:55
  • hi, Ross! Laravel 5.4 Commented Jul 3, 2017 at 15:06

1 Answer 1

2

Ok. Logic of this validation in YourFormRequest is next:

  1. Let mark all fields as required and document_num field additionaly as integer. You can add other additional constraints - it dont matter.
  2. In rules method of YourFormRequest check in loop "is user exists for given document_num?".
  3. If it not exists then ok - validation of this field is success.
  4. If it exists then check "is user fullname equals for given fullname. If equals then ok - validation of this field is success. Otherwise if it fails then attach to this field your custom rule that always fails.

Let see this approach on a working example.

YourFormRequest.php

public function rules()
{
    $rules = [
        'fullname.*' => 'required',
        'document_num.*' => 'required|integer',
    ];

    $documentNums = request()->get('document_num');
    $fullnames = request()->get('fullname');

    for ($i = 0; $i < count($documentNums); $i++) {
        $user = User::where('document_num', $documentNums[$i])->first();
        if ($user && ($user->fullname != $fullnames[$i]) {
            $rules['document_num.' . $i] = "document_num_fail:$i"; //some rule that always fails. As argument we pass a row number of field that fails
        }
    }
    return $rules;
}

CustomValidator.php (place it for example in App\Services folder)

namespace App\Services;

class CustomValidator {

    public function documentNumFailValidate($attribute, $value, $parameters, $validator) {
        return false;
    }

    public function documentNumFailReplacer($message, $attribute, $rule, $parameters) {
        return str_replace([':index'], $parameters[0], $message);
    }
}

Here you can see two functions. First - to validate rule (we always pass false cause we need it). Second - it just a replacer for error message. You want to know on what field line was this error (for example on third line and fields: fullname[2] and document_num[2] respectively). As i wrote above in comment for attaching fail rule we give the number of row that fails to the validation method (documentNumFailReplacer method will replace placeholder :index in error message with the given value)

Next step - register this methods in AppServiceProvider.php

public function boot()
{
    Validator::extend('document_num_fail',  'App\Services\CustomValidator@documentNumFailValidate');
    Validator::replacer('document_num_fail', 'App\Services\CustomValidator@documentNumFailReplacer');
}

And final step - define your custom messages in validation.php

'custom' => [
        'document_num.*' => [
            'document_num_fail' => 'Input-ed user name doesn`t match his/her name in DB for specified :attribute (field position/number: :index)',
        ]
    ],

'attributes' => [
    'document_num.*' => 'document number',
],
Sign up to request clarification or add additional context in comments.

9 Comments

omg. gonna check it now. but you are great anyways:) Is it possible to have any of your contacts - I am in constant need of a great advicer in Laravel:)
= "document_num_fail:$i"; - shouldn't it be: = "document_num_fail:'.$i.'' ?
dont matter "document_num_fail:.$i" or "document_num_fail:". $i your variant is not correct. You just need a construction like this: document_num_fail:4
just try the code. You will see if there are some errors.
Tried. It outputs: "FatalThrowableError in Request.php line 727: Type error: Too few arguments to function Symfony\Component\HttpFoundation\Request::get(), 0 passed in /Users/sergeyfomin/code/first/app/Http/Requests/TestFormRequest.php on line 32 and at least 1 expected" and Line 32 is: $documentNums = request()->get()->get('document_num');
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.