Laravel: Why are validation messages not show? - laravel

I use Laravel 5.4 on hosting. My validation method is working, but it doesn't show messages. I do all the needed operations for displaying errors but it doesn't work.
#if($errors->has('recipient'))
<div class="form-group">
<label class="col-lg-2 control-label"></label>
<div class="col-lg-10">
<div class="alert alert-danger">
<ul>
#foreach ($errors->get('recipient') as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
</div>
</div>
#endif
I use {{ csrf_field() }} tokens. Validation rules work if wrong user types are used, but messages are not displayed.
My send method:
public function send(Request $request)
{
$this->validator($request->all())->validate();
$this->create($request->all());
return redirect($this->redirectToAfterSendMessage);
}
My validator code:
protected function validator(array $data)
{
return Validator::make($data, [
"$this->recipient" => [
'sometimes',
'required',
'email',
'exists:users,email',
Rule::notIn([auth()->user()->email])
],
"$this->subject" => 'sometimes|required|min:10',
"$this->message" => 'sometimes|required|min:50',
], $this->validator_messages());
}
My routes:
Route::get('/compose', 'InboxController#compose') ->name('compose');
Route::post('/compose', 'InboxController#send');
Result of dump($errors):
ViewErrorBag {#244 ▼
#bags: []
}

EDITED
To fix your current problem, change $errors->get('recipient') to $errors->all().
It should look like this:
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
--
This isn't a direct solution for your question. However an even better approach (imo) than yours are custom requests. You can quickly generate custom requests by using the following command:
php artisan make:request CustomRequest
After that you can change type from Request to CustomRequest
public function send(CustomRequest $request)
{
$this->create($request->all());
return redirect($this->redirectToAfterSendMessage);
}
And in CustomRequest.php your extract your validation logic like so:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CustomRequest extends FormRequest
{
/**
* 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 [
'name' => 'required',
'email' => 'required',
'message' => 'required',
];
}
public function messages()
{
return [
'name.required' => 'Name is required.',
'email.required' => 'Email is required.',
'message.required' => 'Message is required.',
];
}
}
Hope this helps.

You need to change:
"$this->recipient"
"$this->subject"
"$this->message"
To:
'recipient'
'subject'
'message'

Related

Using the redirect method, errors are not sent to view

When I use return view('login')->withErrors($validator->errors());, I get the errors returned if any. Now, if I use the Redirect method/class, it doesn't return the data.
I need to use redirect. I tested it in several ways, going through the different errors, but nothing works. I've read documentation, blogs and everything I do doesn't work.
I already tried return Redirect::back()->withErrors(['msg' => 'The Message']); and in the blade `{{ session()->get('msg') }}, but nothing .
I need some help as I have tried many things and nothing works.
Controller:
public function checkUserExists(Request $request)
{
$email = $request->input('email');
$validator = Validator::make(
$request->all(),
[
'email' => ['required', 'max:255', 'string', 'email'],
'g-recaptcha-response' => ['required', new RecaptchaRule],
],
$this->messages
);
if ($validator->fails()) {
// return view('login')->withErrors($validator->errors());
// return Redirect::back()->withErrors(['msg' => 'The Message']);
return Redirect::route('login')->withErrors($validator->errors());
// return Redirect::route('login')->withErrors($validator);
// return redirect()->back()->withErrors($validator->errors());
// return Redirect::back()->withErrors($validator)->withInput();
}
...
}
At the moment my bucket is just with this:
{{-- Errors --}}
#if ($errors->any())
<div class="alert alert-danger" role="alert">
<ul>
#foreach ($errors->all() as $key => $error)
<li>
{{ $error }}
</li>
#endforeach
</ul>
</div>
#endif
Version of Laravel: "laravel/framework": "^7.29",
try this code to pass the errors back to the view:
public function checkUserExists(Request $request)
{
$email = $request->input('email');
$validator = Validator::make(
$request->all(),
[
'email' => ['required', 'max:255', 'string', 'email'],
'g-recaptcha-response' => ['required', new RecaptchaRule],
],
$this->messages
);
if ($validator->fails()) {
return redirect()->back()->withErrors($validator)->withInput();
}
...
}
& in your view, you can access the errors using with:
{{-- Errors --}}
#if ($errors->any())
<div class="alert alert-danger" role="alert">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
this should work if your view is correct
and you are using the correct path to your view
in your redirect()->back() method

Livewire validateOnly with validate in the same component

I have a little problem with the data validation with livewire ( laravel ).
I noticed that when I set up the validation in real time ( validateOnly() ), the information entered in the form is validated in real time. At this level everything is fine.
But when I click on the button to submit the form (even though the form contains errors), the form is unfortunately sent to my function defined in the wire:submit.
So my question is : is it possible to revalidate the information in the wire:submit method that receives the data after the form is submitted ? If so, how can I do that?
PS: I tried to set the validate method in my wire:submit function but nothing happens. It blocks the form from being submitted but it doesn't give me an error .
My source code :
<?php
class UserProfile extends Component
{
use WithFileUploads;
public $countries = [];
public $profile = [];
protected function rules() {
if ( !LivewireUpdateProfileRequest::authorize() ) {
return abort(403, "Your are not authorized to make this request !");
}
$rules = LivewireUpdateProfileRequest::rules();
if ( !empty($this->profile['phone']) ) {
$rules['profile.phone'] = [ 'required', 'phone_number:' . $this->profile['phone'] ];
}
return $rules;
}
public function mount()
{
$this->countries = Countries::all();
$this->profile = Auth::user()->toArray();
}
public function updateUserProfile()
{
$validatedData = $this->validate();
dd( $validatedData );
}
public function updated($key, $value)
{
$this->validateOnly($key);
}
public function render()
{
return view('livewire.user-profile');
}
}
Html source :
<form action="" method="POST" wire:submit.prevent="updateUserProfile">
<input name="profile.email" type="email" wire:model="profile.email" />
#error('profile.email') {{ $message }} #enderror
<input name="profile.phone" type="tel" wire:model="profile.phone" />
#error('profile.phone') {{ $message }} #enderror
</form>
Here is LivewireUpdateProfileRequest content :
<?php
namespace App\Http\Requests\Web;
use Illuminate\Foundation\Http\FormRequest;
class LivewireUpdateProfileRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public static function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public static function rules()
{
return [
'profile' => ['required', 'array', 'size:10'],
'profile.firstname' => ['required', 'string'],
'profile.lastname' => ['required', 'string'],
'profile.email' => ['required', 'email'],
'profile.phone' => ['required', 'phone_number:33'],
'profile.gender' => ['required', 'gender'],
'profile.image' => ['sometimes', 'image', 'mimes:png,jpg,jpeg'],
'profile.address' => ['required', 'string'],
'profile.city' => ['required', 'string'],
'profile.country_id' => ['required', 'exists:countries,id'],
'profile.birth_at' => ['required', 'date', 'min_age:18'],
];
}
}
Usually in your saving method you would run validation once more for all fields. The livewire docs share this example:
Livewire Component:
class ContactForm extends Component
{
public $name;
public $email;
protected $rules = [
'name' => 'required|min:6',
'email' => 'required|email',
];
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function saveContact()
{
$validatedData = $this->validate();
Contact::create($validatedData);
}
}
With this HTML:
<form wire:submit.prevent="saveContact">
<input type="text" wire:model="name">
#error('name') <span class="error">{{ $message }}</span> #enderror
<input type="text" wire:model="email">
#error('email') <span class="error">{{ $message }}</span> #enderror
<button type="submit">Save Contact</button>
</form>
This should validate the inputs near-realtime using the updated-method and on submit using the saveContact-method.
If you could share your code, we could debug it easier.
Source: https://laravel-livewire.com/docs/2.x/input-validation#real-time-validation

Error App\Http\Requests\AddUserRequest::fails does not exist

I get this error when I want to insert data into the table and return a message.
Here is my code.
When I entered the form and submitted, an error occurred: Method App\Http\Requests\AddUserRequest::fails does not exist.
Code In Router:
/**************Quản lý user*****************/
Route::get('admin/manage-user', 'UserController#getList')->middleware('admin');
Route::get('admin/manage-user/add', 'UserController#indexAdd')->middleware('admin');
Route::post('admin/manage-user/add', 'UserController#getAdd')->middleware('admin');
Code In UserController:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use App\Http\Requests\AddUserRequest;
class UserController extends Controller
{
//
public function getList()
{
$data = User::paginate(10);
return view('admin.manage-user',['data' => $data]);
}
public function indexAdd()
{
return view('admin.add-user');
}
public function getAdd(AddUserRequest $request)
{
if($request->fails())
{
return redirect('admin.add-user')
-> withInput()
-> withErrors($request);
}else
{
User::create([
'name' => $request->username,
'email' => $request->email,
'password' => Hash::make($request->pass1),
'level' => 0,
]);
return redirect('admin.add-user')->with('success',"Done!!");
}
}
}
Code In view:
#extends('layouts.admin')
#section('title','Add User')
#section('content')
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-6">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Add User</h3>
</div>
<!-- /.box-header -->
<!-- form start -->
<form role="form" action="{{url('admin/manage-user/add')}}" method="post">
<div class="box-body">
#csrf
<div class="form-group">
#if (session('success'))
<div class="alert alert-success">
<p>{{ session('success') }}</p>
</div>
#endif
#if ($errors->any())
<div class="alert alert-danger">
<b>Lỗi!! Bạn vui vòng kiểm tra lại:</b>
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
</div>
In AddUserRequest:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Request;
class AddUserRequest extends FormRequest
{
/**
* 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 [
'username' => 'required|max:200',
'email' => 'required|email|unique:users',
'pass1' => 'required|min:6',
'pass2' => 'same:pass1',
];
}
}
Thank you for your help!
you don't need to put that check, because data is already validated through your request
public function getAdd(AddUserRequest $request)
{
User::create([
'name' => $request->username,
'email' => $request->email,
'password' => Hash::make($request->pass1),
'level' => 0,
]);
return redirect('admin.add-user')->with('success',"Done!!");
}
AddUserRequest is a FormRequest it doesn't have fails method. For FormRequest you don't need to check fails, it automatically validate your request data using rules provided in that class and throw validation error, for details check here.
For FormRequest validation you use it like this
public function getAdd(AddUserRequest $request)
{
//all code here executed after validation
User::create([
'name' => $request->username,
'email' => $request->email,
'password' => Hash::make($request->pass1),
'level' => 0,
]);
return redirect('admin.add-user')->with('success',"Done!!");
}
If you need to check validation in you controller then use manual validation like this.
public function getAdd(Request $request)
{
$validator = Validator::make($request->all(), [
'username' => 'required|max:200',
'email' => 'required|email|unique:users',
'pass1' => 'required|min:6',
'pass2' => 'same:pass1',
]);
if($validator->fails())
{
return redirect('admin.add-user')
-> withInput()
-> withErrors($request);
}else
{
User::create([
'name' => $request->username,
'email' => $request->email,
'password' => Hash::make($request->pass1),
'level' => 0,
]);
return redirect('admin.add-user')->with('success',"Done!!");
}
}

Laravel 5.2 validation errors

I have some trouble with validation in Laravel 5.2
When i try validate request in controller like this
$this->validate($request, [
'title' => 'required',
'content.*.rate' => 'required',
]);
Validator catch error, but don't store them to session, so when i'm try to call in template this code
#if (isset($errors) && count($errors) > 0)
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
Laravel throw the error
Undefined variable: errors (View: /home/vagrant/Code/os.dev/resources/views/semantic/index.blade.php)
When i'm try validate with this code
$validator = Validator::make($request->all(), [
'title' => 'required',
'content.*.rate' => 'required'
]);
if ($validator->fails()) {
return redirect()
->back()
->withInput($request->all())
->withErrors($validator, 'error');
}
Variable $error also not available in template but if i try to display errors in controller
if ($validator->fails()) {
dd($validator->errors()->all());
}
Errors displays but i can't access to them from template.
What's wrong?
Update as of Laravel 5.2.27
Laravel now supports the web middleware by default as you can see here: source
In other words, you no longer need to wrap your routes around the web middleware group because it does it for you in the RouteServiceProvider file. However, if you are using a version of Laravel between 5.2.0 and 5.2.26, then refer to the method below:
Below only applies to Laravel 5.2.0 to 5.2.26
Without seeing your routes.php or Kernel.php file, here is what I suspect is happening.
The way middlewares work has changed from 5.2 and 5.1. In 5.1, you will see this in your app/Http/Kernel.php file:
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
];
This array is your application's global HTTP middleware stack. In other words, they run on every request. Take a note at this particular middleware: Illuminate\View\Middleware\ShareErrorsFromSession. This is what adds the $errors variable on every request.
However, in 5.2, things have changed to allow for both a web UI and an API within the same application. Now, you will see this in that same file:
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
];
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
],
'api' => [
'throttle:60,1',
],
];
The global middleware stack now only checks for maintenance. You now have a middleware group called "web" that includes a bulk of the previous global middleware. Remember that it is like this to allow for both a web UI and an API within the same application.
So how do we get that $errors variable back?
In your routes file, you need to add your routes within the "web" middleware group for you to have access to that $errors variable on every request. Like this:
Route::group(['middleware' => ['web']], function () {
// Add your routes here
});
If you aren't going to build an API, another option is to move the "web" middlewares to the global middleware stack like in 5.1.
Try using
return redirect()->back()
->withInput($request->all())
->withErrors($validator->errors()); // will return only the errors
Try to replace:
->withErrors($validator, 'error');
with:
->withErrors($validator);
// Replace
Route::group(['middleware' => ['web']], function () {
// Add your routes here
});
// with
Route::group(['middlewareGroups' => ['web']], function () {
// Add your routes here
});
I have my working validation code in laravel 5.2 like this
first of all create a function in model like this
In model add this line of code at starting
use Illuminate\Support\Facades\Validator;
public static function validate($input) {
$rules = array(
'title' => 'required',
'content.*.rate' => 'required',
);
return Validator::make($input, $rules);
}
and in controller call this function to validate the input
use Illuminate\Support\Facades\Redirect;
$validate = ModelName::validate($inputs);
if ($validate->passes()) {
///some code
}else{
return Redirect::to('Route/URL')
->withErrors($validate)
->withInput();
}
Now here comes the template part
#if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
and Above all the things you must write your Route like this
Route::group(['middleware' => ['web']], function () {
Route::resource('RouteURL', 'ControllerName');
});
Wrap you Routes in web middleware like below:
Route::group(['middleware' => ['web']], function () {
// Add your routes here
});
and In app\Http\Kernel.php move \Illuminate\Session\Middleware\StartSession::class from the web $middlewareGroups to $middleware
Hope it will solve your problem.
Route
Route::group(['middlewareGroups' => ['web']], function () {
// Add your routes here
Route::resource('/post', 'PostController');
});
Functions
public function store(Request $request){
$this->validate($request, [
//input field names
'title' => 'required|max:20',
'body' => 'required',
]);
}
View
#if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
This will work
Route::group(['middlewareGroups' => ['web']], function () {
// Add your routes here
});
as well as this also works
Route::post('location',array(
'as'=>'location',
'middlewareGroups'=>'web',
'uses'=>'myController#function'
));
// Controller
$this->validateWith([
'title' => 'required',
'content.*.rate' => 'required',
]);
// Blade Template
#if ($errors->has('title'))
<span class="error">
<strong>{{ $errors->first('title') }}</strong>
</span>
#endif
#if ($errors->has('anotherfied'))
<span class="error">
<strong>{{ $errors->first('anotherfied') }}</strong>
</span>
#endif
Find the documentation.

Laravel flash message validation

I am creating a CRUD of books and what I wanted to do is like the generated auth files that if someone registers and didn't input any in the textbox, a flash message will return. I am doing that now in my crud but I can only make a flash message when a book is successfully created. This is my store function
public function store(Request $request)
{
$this->validate($request, [
'isbn' => 'required|',
'title' => 'required',
'author' => 'required',
'publisher' => 'required'
]);
Session::flash('msg', 'Book added!');
$books = $request->all();
Book::create($books);
return redirect('books');
}
And in my home.blade.php
#if(Session::has('msg'))
<div class="alert alert-success">
{{ Session::get('msg') }}
</div>
#endif
This actually works but I want to show some ready generated error flash when someone didnt complete fields. How can I do that?
It's pretty simple, first there's a sweet nice feature that is the redirect()->with()
So your controller code could be:
public function store(Request $request)
{
$this->validate($request, [
'isbn' => 'required|',
'title' => 'required',
'author' => 'required',
'publisher' => 'required'
]);
if(Book::create($books)){
$message = [
'flashType' => 'success',
'flashMessage' => 'Book added!'
];
}else{
$message = [
'flashType' => 'danger',
'flashMessage' => 'Oh snap! something went wrong'
];
}
return redirect()->action('BooksController#index')->with($message);
}
Then on your view:
#if (Session::has('flashMessage'))
<div class="alert {{ Session::has('flashType') ? 'alert-'.session('flashType') : '' }}">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
{{ session('flashMessage') }}
</div>
#endif
Bonus you can put this on your footer, so the alerts boxes will vanish after 3 seconds:
<script>
$('div.alert').delay(3000).slideUp(300);
</script>
You could get the individual errors for a field
{!! $errors->first('isbn'); !!}
or you can get all the errors
#foreach ($errors->all() as $error)
<div>{{ $error }}</div>
#endforeach
you can use try catch like this
try{
$books = $request->all();
Book::create($books);
Session::flash('msg', 'Book added!');
}
catch(Exception $e){
Session::flash('msg', $e->getmessage());
}

Resources