Prevent overwriting errors message on a page - laravel

I have a page with 2 separated forms, routes and requests.
In this forms I have a field with the same name (for example in each form I have email field).
The problem is when I validating one forms and when form have error, in both forms the error will show.
How can I prevent overwriting errors ?
This is my codes:
Register Request :
class RegisterFormRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'email' => 'required|email|unique:users',
'name' => 'required',
'location' => 'required'
];
}
}
Login Request:
class LoginFormRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'email' => 'required|email',
'password' => 'required'
];
}
}
in blade I use this code above of email field in both forms:
{{$errors->has('email') ? 'has-error' : null }}
When I don't enter email in Login form and submit, the error will show above of email field in Register form too.

Finally I found the solution.
I should add $errorBag variable in Request file:
class RegisterFormRequest extends FormRequest
{
protected $errorBag = 'register';
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'email' => 'required|email|unique:users',
'name' => 'required',
'location' => 'required'
];
}
}
and in blade:
{{$errors->register->has('email') ? 'has-error' : null }}

I have a solution but I am not sure if it is the best way of doing it. The login controller uses the AuthenticatesUsers trait which contains a method sendFailedLoginResponse
By overriding this method in LoginController, you can name the error message bag like this:
protected function sendFailedLoginResponse(Request $request)
{
$errors = [$this->username() => trans('auth.failed')];
if ($request->expectsJson()) {
return response()->json($errors, 422);
}
return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
->withErrors($errors, 'login');
}
Then, in your blade file you can maybe do something like this:
#if (! $errors->login->isEmpty())
<ul>
#foreach ($errors->login->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
#endif

Related

How do I show custom error messages with Laravel form requests?

I am new to Laravel, and have made a UserRequest class that handles validating incoming sign up requests. This is what I have inside it:
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'firstname' => 'required|string',
'lastname' => 'required|string',
'email' => 'required|email',
'password' => 'required|string|min:6',
];
}
/**
* Custom message for validation
*
* #return array
*/
public function messages()
{
return [
'firstname.required' => 'First name is required!',
'lastname.required' => 'Last name is required!',
'email.required' => 'Email is required!',
'password.required' => 'Password is required!'
];
}
My question is do these error messages automatically show if the user doesn't enter a field, or is there anything else I need to do, ie in my controller?
Thanks!
you must include the UserRequest in your controller e.g.
use App\Http\Requests\UserRequest;
And make sure you define your incoming request as a UserRequest (and not a regular Laravel Request) e.g.
public function update(UserRequest $request)
The validation should then be performed automatically.

Laravel - How to Validate Grading System in Model and Controller

I am developing A web Application using Laravel-5.8 framework. I have a Model Class as shown below:
<?php
namespace App;
use App\Model;
class Gradesystem extends Model
{
protected $table = 'grade_systems';
}
Also my Controller is shown below:
public function store(Request $request){
$request->validate([
'grade_system_name' => 'required|string|max:255',
'point' => 'required',
'grade' => 'required',
'from_mark' => 'required',
'to_mark' => 'required',
]);
$gpa = new Gradesystem;
$gpa->grade_system_name = $request->grade_system_name;
$gpa->point = $request->point;
$gpa->grade = $request->grade;
$gpa->from_mark = $request->from_mark;
$gpa->to_mark = $request->to_mark;
$gpa->save();
}
How do I validate, probably from the Model or the Controller between from_mark and to_mark. Also, from_mark should not be greater that or equal to to_mark.
It must not allow a number that falls in the range of already existing value. For example if from_mark is 0 and to_mark is 49 are already in database. So, if a user enters from_mark or to_mark to be 30, it must not allow it.
How do I achieve this?
Thank you.
For custom Validations its better use Rule Objects, where you can implement the logic of your validation.
An Example:
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class Uppercase implements Rule
{
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
return strtoupper($value) === $value;
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'The :attribute must be uppercase.';
}
}
You can see the info in the Laravel documentation
Hope this can help you
I did not understand entire validation you asked but this will help. With same way you can write any other validation on from_mark and to_mark.
$validator = Validator::make($request->all(), [
'grade_system_name' => 'required|string|max:255',
'point' => 'required',
'grade' => 'required',
'from_mark' => 'required',
'to_mark' => 'required',
]);
if ($validator->fails()) {
return redirect()->back()->withInput()->withErrors();
}
if ($request->get('from_mark') < $request->get('to_mark')) {
return redirect()->back()->withInput()->withErrors();
}

laravel request validation rules pass parameter

I'm going straight to the point here, I am wondering if it is possible to pass a parameter on a validation rule in Laravel.
Here's my code:
I need to pass the $product->id to the ProductUpdateRequest class.
I've read some articles and to no avail can't pass a parameter into it. my other solution was to not use the validation rule class and do the validation directly on the controller by using $request->validate[()]. Since I can access the $product->id on the controller I can easily do the validation. but out of curiosity is there a way for me to pass the $product->id on the validation class?
CONTROLLER
public function update(ProductUpdateRequest $request, Product $product)
{
$request['detail'] = $request->description;
unset($request['description']);
$product->update($request->all());
return response([
'data' => new ProductResource($product)
], Response::HTTP_CREATED);
}
VALIDATION RULE
public function rules()
{
return [
'name' => 'required|max:255|unique:products,name'.$product->id,
'description' => 'required',
'price' => 'required|numeric|max:500',
'stock' => 'required|max:6',
'discount' => 'required:max:2'
];
}
Any suggestions/answers/help would be highly appreciated.
You can get the resolved binding from request
$product = $this->route('product');
Inside your rules method you can get the product instance with the above method.
public function rules()
{
$product = $this->route('product');
return [
'name' => 'required|max:255|unique:products,name'.$product->id,
'description' => 'required',
'price' => 'required|numeric|max:500',
'stock' => 'required|max:6',
'discount' => 'required:max:2'
];
}
It works when you make a function with this Product $product (when you used the Resource route in most cases)
public function update(ProductUpdateRequest $request, Product $product)
{
// code goes here
}
but if you make it like the below it won't work ()
public function update(ProductUpdateRequest $request, $id)
{
// code goes here
}
This is how I would validate unique product name on update. I pass the product ID as a route parameter, the use the unique validation rule to validate that it the product name does't exist in the Database except for this product (id).
class ProductController extends Controller {
public function update(Request $request, $id) {
$this->validate($request, [
'name' => 'required|max:255|unique:products,name'.$id,
]);
// ...
}
}
For custom request in validation rule you can put in your
View :
<input type="hidden" value="product_id">
In Validation Request :
public function rules()
{
$product_id = $this->request->get('product_id');
return [
//
];
}

JSON errors of LoginController and RegisterController should be strings not arrays

I am using Laravel 5.5.14 (php artisan --version). I am using Laravel to create just a REST API.
When I get errors, the shape of it looks like this:
[
'message' => 'The given data was invalid.',
'errors' => [
'email' => ['The email field is required.'],
'password' => ['The password field is required.']
]
]
My
We see inside the errors array, each field (email, password) instead of being strings, is an array of a single string. Can there ever be more then one error is this why it is an array? Even if there is more then one error, I wanted to tell Laravel just report the first error without an array, is this possible?
In my api.php I have this:
Route::post('login', 'Auth\LoginController#login');
Route::post('logout', 'Auth\LoginController#logout');
Route::post('register', 'Auth\RegisterController#register');
My LoginController.php looks like this:
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function login(Request $request)
{
$this->validateLogin($request);
if ($this->attemptLogin($request)) {
$user = $this->guard()->user()->load('pets');
$user->generateToken();
return $user;
}
return $this->sendFailedLoginResponse($request);
}
public function logout(Request $request)
{
$user = Auth::guard('api')->user();
if ($user) {
$user->api_token = null;
$user->save();
}
return ['ok' => true];
}
And my RegisterController.php looks like this:
public function __construct()
{
$this->middleware('guest');
}
/**
* The user has been registered.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function registered(Request $request, $user)
{
$user->generateToken();
return response()->json($user, 201);
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
Override validateLogin to the following or you could give it a different name and call it from your controller function-
public function validateLogin($request){
$rules = [
'user_name' => 'required|string',
'password' => 'required|string',
];
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
$errorResponse = $this->validationErrorsToString($validator->errors());
return response()->json(['message' => 'The given data was invalid.', 'errors' => $errorResponse],400);
}
}
And make another function to transform your response to expected format with this method-
private function validationErrorsToString($errArray) {
$valArr = array();
foreach ($errArray->toArray() as $key => $value) {
$valArr[$key] = $value[0];
}
return $valArr;
}
And don't forget to add this at the start of your controller file-
use Validator;
Hope this helps you :)
From the docs:
The $errors variable will be an instance of Illuminate\Support\MessageBag
An example of displaying errors from the docs:
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif

Controller method not found laravel

Hello i have been using implicit controllers for a hile now but today i am having an issue i just cannot understand, i have the following in my Route.php:
/**
* Purchase
*/
Route::controllers([
'purchase' => 'PurchaseController'
]);
and in my controller i have created this method:
public function postNsano(NsanoRequest $request)
{
$data = [
'code' => $request->code,
'msg' => $request->msg,
'reference' => $request->referencecode
];
if ($request->code == "00")
{
Session::put('nsano_callback_post_data', $data);
return [
'code' => '00',
'msg' => 'success'
];
}
else
{
return [
'code' => '01',
'msg' => 'rollback'
];
}
}
Now for some reason when i try and post to this URL:
sample.com/purchase/nsano
I get this error: "Controller Method Not Found"
Which is odd for me because i can see the method right there.
I took out the $request and just used Input::get() instead and now it works can someone please explain this to me?
This is my request:
class NsanoRequest extends Request {
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'code' => 'required',
'msg' => 'required',
'reference' => 'required'
];
}
}
Implicit controller routing needs the HTTP verb in the method name:
public function postNsano(NsanoRequest $request)
{
//
}
Your request validates do not correct so it jumps to an url to prompt error but not found.
If you add some parameters like this and than OK.

Resources