I am humbly seeking a help on how to go about displaying error message in CI4. i have create a controller like this:
public function login()
{
$validation = \config\services::validation();
$errors = array('email' => 'bad email',
'pass' => 'bad pass ');
if(!$this->validate(array('email' => 'required',
'pass' => 'required')))
{
echo view('login', array('validation' => $this->validator));
}
else
{
print 'success';
}
}
while a tested each of the error reporting function below:
$validation->listErrors();
$validation->listErrors('list');
$validation->showError();
$validation->showError('sigle');
$validation->showError('email');
but non of these function work, if i entered correct data it print success as assign but upon wrong data it all show the same error message which is:
Call to a member function listErrors() on null.
Call to a memberfunction listErrors() on null.
Call to a member function showError()on null.
Call to a member function ShowError() on null.
call form helper in your controller before your validation start
helper('form');
and i re-arrange ur code like this
public function login()
{
$data = [
'validation' => \config\services::validation()
];
if ($this->request->getMethod() == "post") { // if the form request method is post
helper('form');
$rules = [
'email' => [
'rules' => 'required',
'errors' => [
'required' => 'bad email'
]
],
'pass' => [
'rules' => 'required',
'errors' => [
'required' => 'bad pass'
]
]
];
if (!$this->validate($rules)) {
echo view('login', array('validation' => $this->validator));
} else {
// whatever you want todo
}
}
echo view('login', $data);
}
in your login view, if you want to call all error list you got use this method $validation->listErrors();
if you want to call a specific error use this method $validation->listErrors('email');
if you want to check is the specific field returning an error use this method $validation->hasError('email'))
i hope this help you to solve your problem
Related
I make form by React. After submitted form, I need to validate data from Laravel. Problem is that sending data is diffrent than normal form. So any values from dorm is in array data.
//normal form
$request->title
//sending from React
$request->data['title']
So, look at this code
class articleRequest extends Request
{
public function rulse(){
return [
'title' => 'required',
//other rules
];
}
}
class ArticleController extends Controller
{
public function atoreArticle(articleRequest $request){
Textads::create([
'title'=> $request->data['title'],
//other
]);
}
}
But I have an error that title field is required. Without valdiation everything is ok. How I can solve my problem?
You can try this -
$rules = [
'title' => 'required',
//other rules
];
Validator::make($request->all(), $rules)->validate();
will this work? or $request->all()->data ?
$validator = Validator::make($request->data, [
title'' => 'required'
],[
//custom error message if needed
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'data' => $validator->messages(),
'message' => "error"
], 422);
}
So what i want is to put 'g-recaptcha-response' in a variable to be able to use it in my condition to verify recaptcha but I haven't been able to do this. Is there any way to only use recaptcha field from the array inside validate() because my code as it is, redirects me back to homepage. It goes straight to else statement.
public function contactanospost(Request $request){
$request->validate([
'nombre' => 'required|distinct',
'telefono'=> 'required|telefono',
'correo' => 'required|email',
'mensaje' => 'required',
'g-recaptcha-response' => 'required|captcha',
]);
if(POST['g-recaptcha-response']){ /*here I am trying to
check with a condition if recaptch was really validated once the form is submitted */
$token= POST['g-recaptcha-response'];
$client = new Client();
$response = $client->post('https://www.google.com/recaptcha/api/siteverify', [
'form_params' => array('secret' => 'mycaptchakey',
'response'=> $token /*Checking with google parameters for recaptcha if the user was indeed verified */
)
]);
$resultados = json_decode($response->getBody()->getContents()); //decode with json
if($resultados->success){ /*if this was a success then return a page with parameters from google recaptcha such as: secret, response, remote ip.*/
dd($resultados); /*show the results from verified user and that recaptcha is working*/
$contactanos = Contactanos::create($request->all());/* and create all fields for model Contactanos*/
Mail::to('some#mail')->send(new enviacorreo($contactanos)); /* since it is a contact form then send all the information to some mail*/
\Session::flash('flash_message','Tu mensaje ha sido enviado!'); /* send a message with "email delivered" verification*/
return redirect()->back();
}
else{
\Session::flash('flash_message','Robot');
return redirect('/');
}
}
else{
return redirect('/');
}
}
I'm now able to access request properties using input() what got me confused were my if statements. The real problem is that after:
$resultados = json_decode($response->getBody()->getContents());
next if statement is not getting the expected success but instead it goes straight to else with robot message:
else{
\Session::flash('flash_message','Robot');
return redirect('/');
}
You can access all the properties of the request from the $request object by calling e.g, $request->input('g-recaptcha-response') This is the basic of Accessing the request if you have read through the documentation.
I can lend you a snippet to do this perhaps it will help you rethink how you're validating the captcha:
use GuzzleHttp\Client;
....
$v = Validator::make($request->all(), [
'name' => 'required|min:2',
'email' => 'required|email|max:255',
'subject' => 'sometimes|required|min:3',
'message' => 'required|min:3',
'g-recaptcha-response' => 'sometimes|required'
], [
'g-recaptcha-response.*' => 'Please verify that you are not a robot'
]);
if ($v->fails()) {
return [
'success' => 'no',
'data' => $v->errors()->first()
];
}
if ($request->get('g-recaptcha-response')) {
$verify_form = [
'secret' => env('GOOGLE_RECAPTCHA_SECRET', 'default'), //better to save in config though
'response' => $request->get('g-recaptcha-response')
];
$client = new Client();
$verify_serial = '?'.http_build_query($verify_form);
$response = $client->post('https://www.google.com/recaptcha/api/siteverify'.$verify_serial);
$arrayed_response = json_decode($response->getBody()->getContents(), true);
if(!$arrayed_response['success']){
Log::notice('There is something wrong with the verification of recaptcha: ',$arrayed_response );
return [
'success' => 'no',
'data' => 'Something went wrong in verification process',
];
}
}
The idea is that, you build the secret and response body and use that to request validation check from Google just as you have done but building the query as query parameters directly to the url.
PS: you don't have to return the snippet :)
I have a register user route which takes name , email and password. It works perfectly fine if the data is correct i.e. unique email and params are present, but if the user is already registered then Laravel sends auto error message in its own format. I want return format to be consistent in case of success or failure.
Successful Register return data:
{
"status": "success",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjUsImlzcyI6Imh0dHA6Ly8xMjcuMC4wLjE6ODAwMC9hcGkvYXV0aC9yZWdpc3RlciIsImlhdCI6MTUyMTI3NTc5MiwiZXhwIjoxNTIxMjc5MzkyLCJuYmYiOjE1MjEyNzU3OTIsImp0aSI6Ik1wSzJSYmZYU1dobU5UR0gifQ.fdajaDooBTwP-GRlFmAu1gtC7_3U4ygD1TSBIqdPHf0"
}
But in case of error it sends data in other format.
{"message":"The given data was invalid.","errors":{"email":["The email has already been taken."]}}
I want both of them to be consistent. Success return data is fine. But i want to customize data if failure occurs. Something like this:
{"status":"error","message":"The given data was invalid.","errors":{"email":["The email has already been taken."]}}
Basically, I need status param to be coming with every response.
Also, I had one query while using Postman the output was pure HTML when error occurred the HTML page was default Laravel Page on the other hand when angular sends the same request the error is json format which i just pasted above.
Since angular is getting JSON respose in any case it is fine for me. But why didn't postman showed me that response.
Register Controller:
public function register(RegisterRequest $request)
{
$newUser = $this->user->create([
'name' => $request->get('name'),
'email' => $request->get('email'),
'password' => bcrypt($request->get('password'))
]);
if (!$newUser) {
return response()->json(['status'=>'error','message'=>'failed_to_create_new_user'], 500);
}
return response()->json([
'status' => 'success',
'token' => $this->jwtauth->fromUser($newUser)
]);
}
Register Request Handler:
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required',
'email' => 'required | email | unique:users,email',
'password' => 'required'
];
}
If I understand you correctly, you always get the error-response without the 'status' key.
What happens with your current code, are a couple of things:
RegisterController#register(RegisterRequest $request) is called by a route
Laravel sees you use the RegisterRequest class as an argument, and will instantiate this class for you.
Instantiating this class means it will directly validates the rules.
If the rules are not met, laravel directly responds with the errors found.
This response will always be in laravel's default 'layout' and the code stops there.
Conclusion: Your code is not even triggered when your validation rules are not met.
I've looked into a solution and came up with this:
public function register(Illuminate\Http\Request $request)
{
//Define your validation rules here.
$rules = [
'name' => 'required',
'email' => 'required | email | unique:users,email',
'password' => 'required'
];
//Create a validator, unlike $this->validate(), this does not automatically redirect on failure, leaving the final control to you :)
$validated = Illuminate\Support\Facades\Validator::make($request->all(), $rules);
//Check if the validation failed, return your custom formatted code here.
if($validated->fails())
{
return response()->json(['status' => 'error', 'messages' => 'The given data was invalid.', 'errors' => $validated->errors()]);
}
//If not failed, the code will reach here
$newUser = $this->user->create([
'name' => $request->get('name'),
'email' => $request->get('email'),
'password' => bcrypt($request->get('password'))
]);
//This would be your own error response, not linked to validation
if (!$newUser) {
return response()->json(['status'=>'error','message'=>'failed_to_create_new_user'], 500);
}
//All went well
return response()->json([
'status' => 'success',
'token' => $this->jwtauth->fromUser($newUser)
]);
}
Now, not conforming your validation rules still triggers an error, but your error, and not laravel's built-in error :)
I hope it helps!
In Laravel 8 I added my custom invalidJson with the "success": false:
in app/Exceptions/Handler.php:
/**
* Convert a validation exception into a JSON response.
*
* #param \Illuminate\Http\Request $request
* #param \Illuminate\Validation\ValidationException $exception
* #return \Illuminate\Http\JsonResponse
*/
protected function invalidJson($request, ValidationException $exception)
{
return response()->json([
'success' => false,
'message' => $exception->getMessage(),
'errors' => $exception->errors(),
], $exception->status);
}
This is what i came up with:
function validate(array $rules)
{
$validator = Validator::make(request()->all(), $rules);
$errors = (new \Illuminate\Validation\ValidationException($validator))->errors();
if ($validator->fails()) {
throw new \Illuminate\Http\Exceptions\HttpResponseException(response()->json(
[
'status' => false,
'message' => "Some fields are missing!",
'error_code' => 1,
'errors' => $errors,
], \Illuminate\Http\JsonResponse::HTTP_UNPROCESSABLE_ENTITY));
}
}
Create a helper directory (App\Helpers) and add it into a file. don't forget to add that into your composer.json
"autoload": {
"files": [
"app/Helpers/system.php",
],
},
Now you can call validate() in your controllers and get what you want:
validate([
'email' => 'required|email',
'password' => 'required|min:6|max:32',
'remember' => 'nullable|boolean',
'captcha' => 'prod_required|hcaptcha',
]);
I have made a main method which calls a validation method to check if everything is correct. But when the validation method find a problem and want to return the error and show it to the user the main method will continue with the rest of the code. How could you prevent this from happening? Here is my current code:
public function postUpdateSettings(Request $request)
{
$this->validateSettings($request);
$this->updateSettings($request);
return redirect()->back()->with('succes', 'Your settings has been changed!');
}
private function validateSettings(Request $request)
{
$this->validate($request, [
'email' => 'required|string|email|max:255|unique:users,email,'.Auth::user()->id.'',
'first_name' => 'required|string|max:50|alpha',
'insertion' => 'nullable|max:25|alpha_spaces',
'last_name' => 'required|string|max:50|alpha',
'job' => 'required',
'message' => 'nullable|max:500',
]);
$jobs = $this->getJob();
if(in_array($request->input('job'), $jobs) === false){
return redirect()->route('home');
}
}
I have a small question. I create simple API using Laravel. When I use validation and if it fails, I got a common message:
{
"result": false,
"message": "The given data failed to pass validation.",
"details": []
}
But how can I get details about which field fails and why like that:
{
"result":false,
"message":"The given data failed to pass validation.",
"details":{
"email":[
"The email field is required."
],
"password":[
"The password must be at least 3 characters."
]
}
}
My code in controller looks like this:
protected function validator(array $data)
{
$validator = Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:3',
]);
return $validator;
}
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'role_id' => 2
]);
}
It is better to handle the validator within the same process, like this:
public function register(Request $request){
$validator = Validator::make($request->all(),[
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
]);
if($validator->fails()){
return response()->json([
"error" => 'validation_error',
"message" => $validator->errors(),
], 422);
}
$request->merge(['password' => Hash::make($request->password)]);
try{
$user = User::create($request->all());
return response()->json(['status','registered successfully'],200);
}
catch(Exception $e){
return response()->json([
"error" => "could_not_register",
"message" => "Unable to register user"
], 400);
}
}
You should make sure you're sending the request with the Accept: application/json header.
Without that - Laravel won't detect that it's an API request,
If validation fails, a redirect response will be generated to send the user back to their previous location. The errors will also be flashed to the session so they are available for display. If the request was an AJAX request, a HTTP response with a 422 status code will be returned to the user including a JSON representation of the validation errors.
check the documentation
I used validate in my project:
1.I created app/http/requests/CreateUserRequestForm.php
public function rules()
{
return [
"name" => 'required',
"address" => 'required',
"phnumber" => 'required|numeric',
];
}
public function messages()
{
return [
'name.required' => 'Please Enter Name',
'addresss.required' => 'Please Enter Address',
'phnumber.required' => 'Please Enter PhNumber'
];
}
call the RequestForm in controller
use App\Http\Requests\CreateUserRequestForm;
public function createUser(CreateUserRequestForm $request)
{
// create
$user= UserModel::create([
'name' => $request->input('name'),
'address' => $request->input('address'),
'phnumber' => $request->input('phnumber')
]);
return response()->json(['User' => $user]);
}
Try this i didn't try but it should be work for you.
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.
take reference from here. laravel validation
/**
* Configure the validator instance.
*
* #param \Illuminate\Validation\Validator $validator
* #return void
*/
public function withValidator($validator)
{
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('email', 'Please enter valid email id');
}
});
}
Try this:
public function create(){
// ------ Validate -----
$this->vallidate($request,[
'enter code here`name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:3'
]);
// ------ Create user -----
$user = User::create(['name' => $request->name']);
return response()->json([
'message' => "success",
'data' => $user``
]);
}