How to map errors to the field? - laravel

Below is my server side validation in lumen :
$rules = array(
'prog_code' => 'required',
'payer_id' => 'required',
);
$validator = \Validator::make($post, $rules);
if (!$validator->fails()) {
try {
// Start Logic Here
} catch (\Exception $e) {
}
} else {
$errors = $validator->errors();
return response()->json($errors->all());
}
and it return error like below :
[
"The prog code field is required.",
"The payer id field is required.",
]
but the problem is how I map the error of which field because I want to show the error below the particular text field.
Can we customize error like below :
[
[prog_code] => "The prog code field is required.",
[payer_id] => "The payer id field is required.",
]

The way I achieve the same response was to do:
if ( $validator->fails() ) {
$errors = [];
foreach ( $validator->errors()->toArray() as $field => $message ) {
$errors[$field] = $message[0];
}
return response()->json($errors);
}

If you dump the $errors variable you have an array of errors like your target:
ViewErrorBag {#406
#bags: array:1 [
"default" => MessageBag {#407
#messages: array:1 [
"pin" => array:1 [
0 => "The Programming Code is required Sir!"
]
]
#format: ":message"
}
]
}
$errors variable is injected by validator when there are errors

Related

Specific ID exception laravel 5.4/5.5

I'm working on a functionality where only a user with the ID number 3 can bet if the match is 1 minute away from starting, it's a success, but now those matches that has the status "Open" is not allowed to place bets. here is the code:
public function *addMatchBet*(Request $request){
$rules = [
'matchid' => 'required|integer|exists:matches,id',
'teamid' => 'required|integer|exists:teams,id',
'bet_amount' => 'required|integer|min:100'
];
$validation = \**Validator**::make($request->all(), $rules);
if ($validation->passes()) {
$user = \**Auth**::user();
$match = \App\**Match**::find($request->matchid);
$team = \App\**Team**::find($request->teamid);
if(!in_array($team->id, [$match->team_a, $match->team_b])) {
return [
'success' => false,
'errors' => [
'bet' => ['Match teams have been updated! Please refresh
page and try again.']
]
];
}
if($match && $match->status == 'open') {
$betCount = $user->bets
->where('match_id', $request->matchid)
->count();
if($match->isClosing(0)) {
return [
'success' => false,
'errors' => [
'bet' => ['Could no longer bet. This match is now
starting!']
]
];
}
}
}
}
Any ideas anyone? TYIA
I've found a solution, this was the code:
if($match && $match->isClosing(0)) {
if($user->id == 3){
$betCount = $user->bets
->where('match_id', $request->matchid)
->count();
}
else{
return [
'success' => false,
'errors' => [
'bet' => ['Could no longer bet. This match is now starting!']
]
];
}
}

Get Json Response when error occured in laravel api

I am working with Laravel and I want JSON response of error which is thrown by request.
For example, using duplicated email address during signup returns:
{
"email": [
"The email has already been taken."
]
}
But I want the response to be like this:
{
"success": false,
"errors": [ 'errors' ]
}
Thanks in advance.
$validator = Validator::make($input);
if (!$validator->fails()) {
$responseMessage['success'] = true;
} else {
$responseMessage['success'] = false;
$responseMessage['error'] = $validator->errors();
}
return responseMessage;
If you are using validator then do like this -
$validator = Validator::make($input, $rules);
if ($validator->fails()) {
$error = array_flatten($validator->messages()->toArray());
$response['response'] = [
"success" => false,
"error" => $error
];
return $response;
}
Hope this will work for you.
To return a json error use:
$message = 'Self defined error message';
return response()->json([['error' => $message]], 400);
400 being the http status code you want to return, could be anything you desire. In this case you would likely want to return 400 (Bad Request).
Output for the code above:
[
{
"error":"Self defined error message"
}
]
$messages = [
'email.unique' => $request->email . " has been used",
];
$validator = Validator::make($request->email, [
'email' => 'required|max:255|email|unique:users'
], $messages);
if ($validator->fails()) {
return response()->json($validator->messages(), 200);
Hope this can help you :)

How to get common validation error message for array field

I need to validate a request with image and tags. How to return a common validation error message for tags.
$this->validate($request, [
'image' => 'required|image,
'tags.*' => 'string'
]);
Currecnt message is.
{
"image": [
"The image field is required."
],
"tags.0": [
"The tags.0 must be a string."
],
"tags.1": [
"The tags.1 must be a string."
]
}
Expected message is.
{
"image": [
"The image field is required."
],
"tags": [
"The tags must be a string."
]
}
Have you tried this,
$this->validate($request, [
'image' => 'required|image,
'tags.*' => 'string'
],$messages = [
'tags.*' => 'The tags must be a string.'
]);
I'm not quit sure but this might work for you.
I think you should try with similar below example:
public function messages()
{
$messages = [];
foreach ($this->request->get('tags') as $key => $val) {
$messages['tags.' . $key . '.string'] = 'The tags must be a string.'
}
return $messages;
}
Hope this work for you !!!
You can add messages with a * to your translation file, as documented.
'custom' => [
'tags.*' => [
'string' => 'The tags must be a string.',
]
],

Better way for testing validation errors

I'm testing a form where user must introduce some text between let's say 100 and 500 characters.
I use to emulate the user input:
$this->actingAs($user)
->visit('myweb/create')
->type($this->faker->text(1000),'description')
->press('Save')
->see('greater than');
Here I'm looking for the greater than piece of text in the response... It depends on the translation specified for that validation error.
How could do the same test without having to depend on the text of the validation error and do it depending only on the error itself?
Controller:
public function store(Request $request)
{
$success = doStuff($request);
if ($success){
Flash::success('Created');
} else {
Flash::error('Fail');
}
return Redirect::back():
}
dd(Session::all()):
`array:3 [
"_token" => "ONoTlU2w7Ii2Npbr27dH5WSXolw6qpQncavQn72e"
"_sf2_meta" => array:3 [
"u" => 1453141086
"c" => 1453141086
"l" => "0"
]
"flash" => array:2 [
"old" => []
"new" => []
]
]
you can do it like so -
$this->assertSessionHas('flash_notification.level', 'danger'); if you are looking for a particular error or success key.
or use
$this->assertSessionHasErrors();
I think there is more clear way to get an exact error message from session.
/** #var ViewErrorBag $errors */
$errors = request()->session()->get('errors');
/** #var array $messages */
$messages = $errors->getBag('default')->getMessages();
$emailErrorMessage = array_shift($messages['email']);
$this->assertEquals('Already in use', $emailErrorMessage);
Pre-requirements: code was tested on Laravel Framework 5.5.14
get the MessageBag object from from session erros and get all the validation error names using $errors->get('name')
$errors = session('errors');
$this->assertSessionHasErrors();
$this->assertEquals($errors->get('name')[0],"The title field is required.");
This works for Laravel 5 +
Your test doesn't have a post call. Here is an example using Jeffery Way's flash package
Controller:
public function store(Request $request, Post $post)
{
$post->fill($request->all());
$post->user_id = $request->user()->id;
$created = false;
try {
$created = $post->save();
} catch (ValidationException $e) {
flash()->error($e->getErrors()->all());
}
if ($created) {
flash()->success('New post has been created.');
}
return back();
}
Test:
public function testStoreSuccess()
{
$data = [
'title' => 'A dog is fit',
'status' => 'active',
'excerpt' => 'Farm dog',
'content' => 'blah blah blah',
];
$this->call('POST', 'post', $data);
$this->assertTrue(Post::where($data)->exists());
$this->assertResponseStatus(302);
$this->assertSessionHas('flash_notification.level', 'success');
$this->assertSessionHas('flash_notification.message', 'New post has been created.');
}
try to split your tests into units, say if you testing a controller function
you may catch valication exception, like so:
} catch (ValidationException $ex) {
if it was generated manually, this is how it should be generated:
throw ValidationException::withMessages([
'abc' => ['my message'],
])->status(400);
you can assert it liks so
$this->assertSame('my message', $ex->errors()['abc'][0]);
if you cannot catch it, but prefer testing routs like so:
$response = $this->json('POST', route('user-post'), [
'name' => $faker->name,
'email' => $faker->email,
]);
then you use $response to assert that the validation has happened, like so
$this->assertSame($response->errors->{'name'}[0], 'The name field is required.');
PS
in the example I used
$faker = \Faker\Factory::create();
ValidationException is used liks this
use Illuminate\Validation\ValidationException;
just remind you that you don't have to generate exceptions manually, use validate method for common cases:
$request->validate(['name' => [
'required',
],
]);
my current laravel version is 5.7

Phalcon validate field if exist post data

I've notice that phalcon validation model will do validation no matter the field do exist in post.
public function validation()
{
$this->validate(new Uniqueness(
array(
"field" => "email",
"message" => "The email is already registered"
)
));
$this->validate(new Email(
array(
"field" => "companyEmail",
"message" => "Email format error"
)
));
return $this->validationHasFailed() != true;
}
In this case even if the user is saving other data rather than email, the email field still being verified. How to make it validate only if the field exist? ( for some field its really not needed to validate everytime )
maybe something like
if( *syntax* ){
$this->validate(new Email(
array(
"field" => "companyEmail",
"message" => "Email format error"
)
));
}
Use a form class (subclass of Phalcon\Forms\Form), add code to check for the existence of the variable in your beforeValidate function and only add the validator if the variable is set.
function beforeValidation($data, $entity)
{
...
$elements = $this->getElements();
if (isset($data['fieldname'])) {
$elements['fieldname']->addValidator(new Email(
array(
"field" => "companyEmail",
"message" => "Email format error"
)
))
...
}
}
Here my solution:
if( !empty($this-companyEmail) ){
$this->validate(new Email(
array(
"field" => "companyEmail",
"message" => "Email format error"
)
));
}
I'm doing this as I am passing the variable via ajax
This is my implementation for Phalcon 3.4
class SometimesOf extends \Phalcon\Validation\Validator\PresenceOf
{
public function __construct(array $options = null)
{
parent::__construct($options);
$this->setOption('allowEmpty', true);
if(!$this->hasOption('message')){
$this->setOption('message', 'Field :field cannot be empty');
}
}
public function isAllowEmpty(Validation $validator, $field)
{
$keys = array_keys($validator->getData());
return !in_array($field, $keys, true);
}
}
And in the validator use it as a...
$validation->add('foo', new PresenceOf());
$validation->add('bar', new SometimesOf());
$messages = $validation->validate($data);

Resources