I am trying to validate a simple form by using Laravel's validator. Looks like validation works fine but i am unable to display errors. Form and controller looks like this.
Form
<h3>Add a New Team</h3>
<form method="POST" action="/teams">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="form-group">
<input class="form-control" name="team_name" value="{{ old('team_name') }}" />
</div>
<div class="form-group">
<button type="submit" class="btn bg-primary">Add Team</button>
</div>
</form>
#if(count($errors))
<div class="alert alert-danger">
<ul>
#foreach($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
Controller Method
public function store(Request $request) {
$this->validate($request, [
'team_name' => 'required|min:10'
]);
$team = new Team;
$team->team_name = $request->team_name;
$team->save();
return back();
}
If i remove web middleware group from my routes, errors displays fine.
Currently my routes.php file looks like this
Route::group(['middleware' => ['web']], function () {
Route::get('/teams', 'TeamsController#create');
Route::post('/teams', 'TeamsController#store');
});
How do i fix this problem ? Any help would be appreciated.
why do use the validation looks like laravel 4 while you are using laravel 5!!
in laravel 5 you need first to make Request class that handle your validation
php artisan make:request RequestName
you will find the request class that you make in
'app/http/Requests/RequestName.php'
and in the rules function you can handle your validation
public function rules()
{
return [
// put your validation rules here
'team_name' => 'required|min:10'
];
}
finally in your controller
use App\Http\Requests\RequestName;
public function store(RequestName $request) {
Team::create($request->all());
return Redirect::back();
}
for more illustration here
I recommend you to use Laravel Form Request
run
artisan make:request TeamRequest
add some logic and rules
class TeamRequest extends Request {
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true; //you can put here any other variable or condition
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
// put your validation rules here
];
}
}
then your contorller code will be like so:
public function store(TeamRequest $request)
{
$team = Team::create($request->all());
return back();
}
you no longer need to validate request and redirect back with errors and other stuff, laravel will do it for you
And you code looks more clean and neat, isn't it?
Write below code in your controller :
// define rules
$rules = array(
'team_name' => 'required|min:10'
);
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails())
{
// something
return Redirect::back()
->withErrors($validator) // send back all errors to the login form
->withInput();
}
else
{
// something
// save your data
$team = new Team;
$team->team_name = $request->team_name;
$team->save();
}
change in View File :
#if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
After a little bit research, i have found that Laravel 5.2 has a RouteServiceProvider and it includes web middleware group for all routes. So i do not have to add the web middleware group to my routes manually. I just removed it from routes.php and problem solved.
If i remove web middleware group from my routes, errors displays fine.
In Laravel 5.2 the web midddleware is automatically applied to your routes in routes.php so no need to apply web middleware again. It is defined in mapWebRoutes() method of RouteServiceProvider.
Related
I coded update status for category. I got a new function in an API
Controller, so when I click submit it is not working.
This is solved when I move to category.update, but I can't because that function is used for something else.
web.php
Route::patch('category/{$category}', 'Admin\CategoryController#change')
->name('category.change');
Route::resource('category', 'Admin\CategoryController')
->middleware('loggedin');
This is the new function for API Controller:
public function change($category, Request $request)
{
$cate = Category::find($category);
if ($cate->category_status == 0) {
$cate->category_status = 1;
$cate->save();
} else {
$cate->category_status = 0;
$cate->save();
}
return back()->with('success', 'Success!');
}
list.blade.php
<form autocomplete="off" action="{{ route('category.change', [$cate->category_id]) }}" method="POST" enctype="multipart/form-data">
#method('PATCH')
#csrf
<button class="fa fa-eye" type="submit"></button>
</form>
First, in route, delete $
Route::patch('category/{category}', 'Admin\CategoryController#change')
->name('category.change');
Second - use route with named param
route('category.change', ['category' => $cate->category_id])
Third - in controller action Request must be first
public function change(Request $request, $category){}
I added a CRUD interface for my user's table, and instead of a delete button, I used a block button. Which blocks a user (sets bloque field in the database from 0 to 1). I added a new function in my controller called block which is supposed to do the job yet I get a MethodNotAllowedHttpException error every time I click the blocking button.
UserController
public function block($id)
{
$user = User::find($id);
$user->bloque = 1;
$user->save();
return redirect('/users')->with('success', 'Utilisateur bloqué');
}
The blocking HTML fragment
<form action="{{ route('users.block', $user->id)}}" method="get">
#csrf
<!-- #method('DELETE')-->
<button class="btn btn-danger" type="submit">Bloquer</button>
</form>
Routes
Route::get('/block', [
'uses' => 'UserController#block',
'as' => 'users.block'
]);
I think the problem is related to id value, It should be instantiated from $request object. Like:
public function block(Request $request)
{
$user = User::find($request->id);
$user->bloque = 1;
$user->save();
return redirect('/users')->with('success', 'Utilisateur bloqué');
}
I manually created a Validator, but i can't find a method to get the validated data.
For Request, validated data return from $request->validate([...])
For FormRequest, it's return from $formRequest->validated()
But with Validator, i don't see a method like those 2 above.
Assuming that you're using Validator facade:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), $rules, $messages, $attributes);
if ($validator->fails()) {
return $validator->errors();
}
//If validation passes, return valid fields
return $validator->valid();
https://laravel.com/api/5.5/Illuminate/Validation/Validator.html#method_valid
If you use the Validator facade with make it will return a validator instance. This validator instance has methods like validate(), fails() and so on. You can look those methods up in the validator class or in the laravel api-documentation.
Writing The Validation Logic
public function store(Request $request)
{
$validatedData = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// The blog post is valid...
}
Displaying The Validation Errors
<!-- /resources/views/post/create.blade.php -->
<h1>Create Post</h1>
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
<!-- Create Post Form -->
I am trying to get validation errors to show up in Laravel.
I have a UserController set up like so:
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
//Use Request;
Use Flash;
Use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* Show the profile for the given user.
*
* #param int $id
* #return Response
*/
public function showProfile($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
public function store(Request $request) {
$this->validate($request, [
'email' => 'required|unique:users|email|max:255',
]);
if($this) {
$input = Request::all();
User::create($input);
return redirect('/');
}
else {
return redirect('/')->withErrors($validator);
}
}
}
In my view (layout.blade.php), I have included:
#if (count($errors) > 0)
#foreach ($errors->all() as $error)
{{!! $errors !!}}
#endforeach
#endif
To account for the route, I have:
Route::group(['middleware' => ['web']], function () {
Route::get('/', function (){
return view('home');
});
});
Unfortunately, when I enter "bad" data that shouldn't be verified, I am not seeing any error (but it is not being stored in the db, so there's that).
One other note, when the blade template is rendered, I am seeing an extra "}" bracket, which I'm not sure why that is there.
In laravel version 5.2.41, the middleware web is thrown out.
Means adding the routes inside Route::group(['middleware' => ['web']], function () { will make the validation not work.
There are a couple things wrong or that can be improved here. The store method on the UserController has a lot of weird issues. $this will always be true because objects are true in php. Also, you pass in $validator into withErrors which doesn't make sense because there's no variable validator.
public function store(Request $request) {
$this->validate($request, [
'email' => 'required|unique:users|email|max:255',
]);
User::create(Request::all());
return redirect('/');
}
The validate method will throw an Illuminate\Foundation\Validation\ValidationException if there is a validation error. This exception should be listed in the $dontReport instance variable in App\Exceptions\Handler as seen below:
protected $dontReport = [
AuthorizationException::class,
HttpException::class,
ModelNotFoundException::class,
ValidationException::class,
];
If you have changed these values, removed, or modified the ValidatesRequest trait you may have broken this functionality.
Your error reporting code is not correct either:
#foreach ($errors->all() as $error)
{!! $errors->first() !!}
#endforeach
There are 3 changes here. First I removed the outer errors size check, this doesn't really get you anything. Next, I fixed your extra } error, the syntax for un-escaping data is {!! $errors->first() !!}. Lastly, I called ->first() this returns the first error associated with that particular field.
I think it's important to note that the validation exception will create a redirect response to the previous page. The logic for determining the previous page can be found in Illuminate\Routing\UrlGenerator::previous().
The errors block should be:
#if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
Assuming you're using Bootstrap for the alerts.
You also don't have $validator defined. You need to do something like this:
$validator = Validator::make($request->all(), [
'email' => 'required|unique:users|email|max:255',
]);
Instead of $this->validate().
That should do it.
If it is still not working and you have tried several things like
Moving ShareErrorsFromSession::class from $middlewareGroups to $middleware
Removing the web.php to web middleware
Try modifying the request headers to
Accept: application/json
Or you can also create a new middleware that will modify the request header like this:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class ModifyAcceptHeaderMiddleware
{
public function handle(Request $request, Closure $next)
{
$request->headers->set('Accept', 'application/json');
return $next($request);
}
}
Try to remove "\Illuminate\Session\Middleware\StartSession::class" from 'middleware' in Kernel.php, it must be only in the 'web' group.
#if(count(($errors->all()) > 0))
#foreach($errors->all() as $error)
<div class="alert alert-danger">
{{$error}}
</div>
#endforeach
#endif
Am working on form validations for newsletter for a project am on, the news letter form appears on every page so it will also appear on the longin and registration page so i decided to make use of Laravel Message Bags to store the news letter errors but it keeps giving me an undefined property error on the actual page i check and output echo the errors, i don't know if am doing something wrong here are the details though!
The Error:
Undefined property: Illuminate\Support\MessageBag::$newsletter
My code In the Controller:
return Redirect::back()->withInput()->withErrors($inputs, "newsletter");
My code in the View:
#if($errors->newsletter->any())
<p>
{{$errors->newsletter->any()}}
</p>
Code in controller:
$post_data = Input::all();
$validator = Validator::make(Input::all(),
array(
'email' => 'required',
'password' => 'required'
));
if ($validator->fails()) {
return Redirect::back()
->withInput()
->withErrors(['auth-validation' => 'ERROR: in validation!']);
}
Code in vew:
#if($errors->any())
#foreach($errors->getMessages() as $this_error)
<p style="color: red;">{{$this_error[0]}}</p>
#endforeach
#endif
The RedirectResponse class function withErrors() doesn't have a second parameter..
The function vendor\laravel\framework\src\Illuminate\Http\RedirectResponse.php -> withErrors():
/**
* Flash a container of errors to the session.
*
* #param \Illuminate\Support\Contracts\MessageProviderInterface|array $provider
* #return \Illuminate\Http\RedirectResponse
*/
public function withErrors($provider)
{
if ($provider instanceof MessageProviderInterface)
{
$this->with('errors', $provider->getMessageBag());
}
else
{
$this->with('errors', new MessageBag((array) $provider));
}
return $this;
}
So, if you really want to use the MessageBag then this should work (didn't test it):
$your_message_bag = new Illuminate\Support\MessageBag;
$your_message_bag->add('foo', 'bar');
return Redirect::back()->withInput()->withErrors($your_message_bag->all());
withErrors should receive the messages from validator object. After your validation process something like:
$validation = Validator::make(Input::all(), $validation_rules);
if (!$validation->passes()){
return Redirect::back()->withInput()->withErrors($validation->messages());
}
I hope it works fine for you.
You can write a function like this
if(!function_exists('errors_for')) {
function errors_for($attribute = null, $errors = null) {
if($errors && $errors->any()) {
return '<p class="text-danger">'.$errors->first($attribute).'</p>';
}
}
}
then in your View
<div class="form-group">
<label for="bio">Bio</label>
<textarea class="form-control" name="bio"></textarea>
</div>
{!! errors_for('bio',$errors) !!}
learnt from Jeffrey Way on Laracasts