Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] Add key/index/iteration placeholders to validation attributes #35754

Closed
wants to merge 3 commits into from
Closed

[8.x] Add key/index/iteration placeholders to validation attributes #35754

wants to merge 3 commits into from

Conversation

amir9480
Copy link
Contributor

@amir9480 amir9480 commented Dec 29, 2020

This pull request provides 3 placeholders for validation attributes/messages when validating arrays
and replaces them for better validation messages.

:key: which is array key.
:index: which is the same key but replaces only numbers (not strings).
:iteration: which is the same index plus one (which more readable and useful for the final user).

An example code before this change:

// Sample request ['items' => [4, 8, 'test', 3]]
public function test(Request $request)
{
	  $attributes = [];
      if(is_array($request->input('items'))) {
	      foreach ($request->input('items') as $key => $value) {
	          $attributes["items.$key"] = 'Item ('.(intval($key) + 1).')';
	      }
	  }
	  Validator::make($request->all(), 
          ['items.*' => 'required|numeric|min:1'],
          [],
          $attributes
      )->validate();
      // The Item (3) must be a number.
}

Same code after this change:

// Sample request ['items' => [4, 8, 'test', 3]]
public function test(Request $request)
{
	  Validator::make($request->all(), 
          ['items.*' => 'required|numeric|min:1'],
          [],
          ['items.*' => 'Item (:iteration)']
      )->validate();
	  // The Item (3) must be a number.
}

There are placeholders for nested arrays too and can be handle by adding an index number at end of the placeholder.

Validator::make(
    ['name' => [['', 'Foo'], ['', 'Bar']]],
    ['name.*.*' => 'required'],
    [],
    ['name.*.*' => 'Name (:iteration0)(:iteration1)']
)->validate();
// Error message 1: The Name (1)(1) field is required.
// Error message 2: The Name (2)(1) field is required.

@taylorotwell
Copy link
Member

Why iterate over the same thing three times?

@amir9480
Copy link
Contributor Author

amir9480 commented Dec 30, 2020

@taylorotwell
There is no specific reason for that.
I just tried to write clean and readable code.

I can merge all of them in one function.
What name should I use for the function to cover (key/index/iteration) at the same time?

@amir9480
Copy link
Contributor Author

amir9480 commented Jan 2, 2021

@taylorotwell

Is replaceKeysPlaceholders fine for all of them?

@taylorotwell
Copy link
Member

Maybe something like replaceArrayPlaceholders.

@taylorotwell
Copy link
Member

I dunno, I think I'm going to skip this one. I would just make a wildcard language line that says something like "All entires require a name" instead of having something like "The name (2)(1) field is required."

@amir9480
Copy link
Contributor Author

amir9480 commented Jan 8, 2021

@taylorotwell

I know I can use something like this.
But when the number of entries is a lot, it's harder for the final user to detect what the problem is.
Also required rule is easier to detect and fix but something like unique or exists is harder and a message like All entries must be valid. is not useful and using an attribute name including the row of field can help more.

The name (2)(1) field is required.

The above message is just a sample created by me for tests and can be replaced with more readable attributes/messages instead of Name (:iteration0)(:iteration1) based on the UI that we using for our application.

I provide more examples, hopefully, I don't need to use the old way I using now to approach this functionality anymore.

Another example:

// Sample request ['items' => [4, 8, 'test', 3]]
public function test(Request $request)
{
	  Validator::make($request->all(), 
          ['items.*' => 'required|numeric|min:1'],
          [],
          ['items.*' => 'Item in row :iteration']
      )->validate();
	  // The Item in row 3 must be a number.
}

Validator::make(
    ['name' => [['', 'Foo'], ['', 'Bar']]],
    ['name.*.*' => 'required'],
    ['name.*.*.required' => 'The field in row :iteration0 and column :iteration1 is required.']
)->validate();
// Error message 1: The field in row 1 and column 1 is required.
// Error message 2: The field in row 2 and column 1 is required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants