How to remove console error 422 (Unprocessable Content) - laravel

I write validation for email in my controller
public function store(Request $request)
{
/*
* validate request
*/
$request->validate([
'email' => ['required', 'unique:leads', 'email'],
]);
return response()->json([],422);
if (\App\Models\Lead::where(['email' => $request->get('email')])->count() > 0) {
// user found
return response()->json([ 'data' => [
'message' => 'lindirizzo email è già registrato'
]], 200);
}
else {
// Register the new user or whatever.
$client = \App\Models\Lead::create(['email' => $request->get('email'),]);
return response()->json([ 'data' => [
'message' => 'Registrato con successo!'
]], 201);
}
}
And when i write the same email in front i get error POST http://127.0.0.1:8000/api/register/leads 422 (Unprocessable Content)
My network respons its ok,
{"message":"validation.unique","errors":{"email":["validation.unique"]}}
But i dont want to show error in console

This line of code is unnecessary.
// ...
return response()->json([],422);
// ...
Remove it.
Writing The Validation Logic
... if the validation fails, the proper response will automatically be
generated. If the validation passes, our controller will continue
executing normally.
Addendum
The block of code below is unnecessary as well since the validation rule 'unique:leads' is sufficient:
// ...
if (\App\Models\Lead::where(['email' => $request->get('email')])->count() > 0) {
// user found
return response()->json([ 'data' => [
'message' => 'lindirizzo email è già registrato'
]], 200);
}
// ...
Remove it as well!
If you wish to have a custom message for the "unique email" validation, add it as the second parameter of the ->validate(...) method:
$request->validate([
'email' => ['required', 'unique:leads', 'email'],
], [
'email.unique' => 'lindirizzo email è già registrato'
]);

First, you need to check is there any email is available already or not in the table.
If you found any count of that email then simply ignore creating a record else you can add that email with a new entry inside the database.
if (Lead::where(['email' => $request->get('email')])->count() > 0) {
return response()->json([ 'data' => [
'message' => 'User data get successfully'
]], 200);
}else{
// Add a user with new email and send json response
}
}

Related

How I can add error message in Laravel validate?

Help plz. "How add error user mistake in laravel" I want show JSON file - error $regex - reqular rules
I need get mistake on not correct sourceUrl
$this->validate($request,[
'title' => 'required|min:10|max:250', //work
'subTitle' =>'sometimes|present|nullable|min:10|max:250', //work
'message' => 'required|min:10',//work
'recommendPic' => 'present|nullable', //work
'pic' => 'required|sometimes', //file - check upload file,image need fix
'sourceUrl' =>'required|regex:'.$regex,
],[
'sourceUrl.regex:'.$regex=>'mistake',
]);
You need to return your failed validation messages, something like the following:
$validation = Validator::make($request->all(), [
'title' => 'required|min:10|max:250', //work
'subTitle' =>'sometimes|present|nullable|min:10|max:250', //work
'message' => 'required|min:10',//work
'recommendPic' => 'present|nullable', //work
'pic' => 'required|sometimes', //file - check upload file,image need fix
'sourceUrl' =>'required|regex:'.$regex,
]);
// if validation fails
if ($validation->fails()) {
return response()->json([
'status' => 'failure',
'errors' => $validation->errors()
], 400);
}
// validation passes
return response()->json(['status' => 'success'], 200);
'sourceUrl.regex:'.$regex=>'mistake', is not valid PHP code.
It should be something like: 'sourceUrl.regex' => 'regex mistake'
This redirects back with the error message regex mistake.
In your view you can print the message with #error('sourceUrl') {{ $message }}#enderror.

Find data before validate form request laravel

I want to update the data using the request form validation with a unique email role, everything works normally.
Assume I have 3 data from id 1-3 with url:
127.0.0.1:8000/api/user/update/3
Controller:
use App\Http\Requests\Simak\User\Update;
...
public function update(Update $request, $id)
{
try {
// UPDATE DATA
return resp(200, trans('general.message.200'), true);
} catch (\Exception $e) {
// Ambil error
return $e;
}
}
FormRequest "Update":
public function rules()
{
return [
'user_akses_id' => 'required|numeric',
'nama' => 'required|max:50',
'email' => 'required|email|unique:users,email,' . $this->id,
'password' => 'required',
'foto' => 'nullable|image|max:1024|mimes:jpg,png,jpeg',
'ip' => 'nullable|ip',
'status' => 'required|boolean'
];
}
but if the updated id is not found eg:
127.0.0.1:8000/api/user/update/4
The response gets The email has already been taken.
What is the solution so that the return of the data is not found instead of validation first?
The code looks like it should work fine, sharing a few things below that may help.
Solution 1: Check if $this->id contains the id you are updating for.
Solution 2: Try using the following changes, try to get the id from the URL segment.
public function rules()
{
return [
'user_akses_id' => 'required|numeric',
'nama' => 'required|max:50',
'email' => 'required|email|unique:users,email,' . $this->segment(4),
'password' => 'required',
'foto' => 'nullable|image|max:1024|mimes:jpg,png,jpeg',
'ip' => 'nullable|ip',
'status' => 'required|boolean'
];
}
Sharing one more thing that may help you.
Some person uses Request keyword at the end of the request name. The Update sounds generic and the same as the method name you are using the request for. You can use UpdateRequest for more code readability.
What I understand from your question is, you need a way to check if the record really exists or not in the form request. If that's the case create a custom rule that will check if the record exists or not and use that rule inside your request.
CheckRecordRule
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class CheckRecordRule implements Rule
{
protected $recordId;
public function __construct($id)
{
$this->recordId = $id;
}
public function passes($attribute, $value)
{
// this will check and return true/false
return User::where('id', $this->recordId)->exists();
}
public function message()
{
return 'Record not found.';
}
}
Update form request
public function rules()
{
return [
'email' => 'required|email|unique:users,email,' . $this->id.'|'. new CheckRecordRule($this->id),
];
}
So when checking for duplicate it will also check if the record really exists or not and then redirect back with the proper message.

Laravel Test on controller returning uncorrect status code

I'm trying to create a test on a rest API using Laravel. My test is in 3 steps : Arrange, act and assert.
During the first step I create an entry in the database. For the second test i query my DB, finally i check if the tests are true or not.
use RefreshDatabase;
/** #test */
public function createTest() {
// Arrange : name & message OK
$message = ChatMessages::create([
'username' => 'My name is long enough',
'message' => 'my message is also OK'
]);
// Act
$getAllMessages = ChatMessages::all();
$this->post('/message', $message->toArray())
->assertStatus(200)
->assertExactJson([
'status' => 'ok', 'chat_message' => $message->toArray()
]);
// assert : if name too short, data is not persisted
$this->assertEquals(sizeof($getAllMessages), 1);
}
My route :
Route::post('/message', 'ChatController#create');
I have the following error message :
Expected status code 200 but received 404.
Failed asserting that false is true.
In my Controller I have this code :
public function create(Request $request) {
$input = $request->validate([
'username' => 'required|string|min:3|max:255',
'message' => 'required|string|min:1',
]);
try {
$message = ChatMessages::create([
'username' => $input['username'],
'message' => $input['message'],
]);
} catch (\Exception $err) {
Log::error("Cannot fetch chat messages");
Log::error($err);
abort(500);
}
return response()->json(['status' => 'ok', 'chat_message' => $message]);
}
$request->validate should give a 302 redirection if not satisfied and 200 if OK.

how to create Custom Validation Rule for during Update a record in CakePHP

I have added a rule to check the previous password on update user record, but the rule also applies to creating a record, I have added 'update' but still, it's not working.
$validator
->scalar('password')
->maxLength('password', 25)
->notEmpty('password', 'Password is required', 'create')
->allowEmpty('password', 'update')
->add('password', 'validFormat', [
'rule' => ['custom', '/^(?=.*[!#$])(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{6,16}$/i'],
'message' => __('Minimum 6 character & alphanumeric with one symbol(!#$) is Required.'),
'allowEmpty' => true
])
->add('password', 'custom', [
'rule' => function($value, $context){
$user = $this->get($context['data']['id']);
if ($user) {
if (!(new DefaultPasswordHasher)->check($value, $user->password)) {
return true;
}
}
return false;
},
'message' => 'You cannot use your previous password',
'allowEmpty' => true
], 'update');
Adding updated does not do anything as it is not something that CakePHP supports there.
If you read Custom Validation Rules you will see that you can use $context['newRecord'] to determine if this is an update or create.
So, the first line in your validation function could be something like
if ($context['newRecord']){
return true; //new passwords are always valid!
}
Alternative way would be to check the $user variable and add an else branch
if($user){
//you already have code here
}else{
//add this else to return TRUE because for new user, new password is OK
return true;
}

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

Resources