This question already has answers here:
Undefined variable: errors in Laravel
(9 answers)
Closed 7 years ago.
This is weird. I've been googling all day trying to find a solution for my problem and most of solutions don't work for me due to different versions or different request - controller handling.
What's happening is this.
I have a form:
<div class="form-group">
Name *
{!! Form::text('name', '', ['class'=>'form-control', 'placeholder'=>'Required field']) !!}
</div>
And a Request:
class ContactFormRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'name' => 'required|max:64',
'email' => 'required|email|max:128',
'message' => 'required|max:1024',
];
}
}
I'm leaving the name field blank so it fails validation, and it should return to the contact form page and show the errors:
#if(count($errors) > 0)
<div class="alert alert-danger">
<ul>
#foreach($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
It shows nothing! If I vardump the $errors variable, I get this:
object(Illuminate\Support\ViewErrorBag)[161]
protected 'bags' =>
array (size=0)
empty
If I fill the form field properly it successfully sends me to the success page and everything works perfect. All I need now is to make this error thing work properly :S
Thank you in advance!
This is a breaking problem with the 5.2 upgrade. What's happening is the middleware which is responsible for making that errors variable available to all your views is not being utilized because it was moved from the global middleware to the web middleware group.
There are two ways to fix this:
1-In your kernel.php file, you can move the middleware \Illuminate\View\Middleware\ShareErrorsFromSession::class back to the protected $middleware property.
2-You can wrap all your web routes with a route group and apply the web middleware to them.
Route::group(['middleware' => 'web'], function() {
// Place all your web routes here...
});
See this
laravel-5-2-errors-not-appearing-in-blade
Related
Taken from lrvl 5.1 documentation, I read:
using these lines in the controller:
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
]);
If validation doesn't pass controller stops execution and redirect back to previous location.
This is happening correctly.
Then doc says:
"$errors variable will always be available in all of your views on every request"
And then suggests the following blade code:
#if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
But actually I'll get a ErrorException undefined variable errors....
What am I missing?
Thanks
I'll answer myself to this question,
just in case It was not clear the commented solution.
(Thanks to train_fox for the hint).
Just add 'web' middleware usage.
in your routing that is target in form action (get/post)
Example:
Route::group(['middleware' => 'web'],
function(){
Route::post('/edit' , 'My_Controller#edit');
});
Variable $errors the becomes available on view to be parsed.
I was doing great so far until I ran into another problem with validation. I'm trying to update a user related table called socialLinks. The problem is every time I update, since it's a model backed form, the prefilled values in the form gets pass through validations and I get a 'has already been taken' error in return.
After doing a bunch of googling, I tried to pass userId through update, but i haven't had any success. I had this problem before but I was validating a column from User. Now I'm trying to validate a column from another table with a relationship with user and nothing I tried before works. Super Frustrating.
my form
{!! Form::model($user_links,['method' => 'PATCH', 'action'=> ['UserController#update_social']]) !!}
<div class='row form-group'>
<div class='col-md-2'>
{!! Form::label('facebook', 'Facebook Username') !!}
</div>
<div class='col-md-7'>
{!! Form::text('facebook', null,['class'=>'form-control']) !!}
</div>
</div>
<div class='row form-group'>
<div class='col-md-2'>
{!! Form::label('twitter', 'Twitter Username') !!}
</div>
<div class='col-md-7'>
{!! Form::text('twitter', null,['class'=>'form-control']) !!}
</div>
</div>
<div class='row form-group'>
<div class='col-md-2'>
{!! Form::label('reddit', 'Reddit Username') !!}
</div>
<div class='col-md-7'>
{!! Form::text('reddit', null,['class'=>'form-control']) !!}
</div>
</div>
<div class='row form-group'>
<div class='col-md-3'>
{!! Form::submit('Save Changes',['class'=>'btn btn-md btn-success']) !!}
{!! Form::close() !!}
routes
Route::get('/account/social','UserController#social');
Route::patch('/account/social','UserController#update_social');
and controllers
public function social(Request $request){
$user = $request->user();
$user_links= $request->user()->links;
return view('user.edit.social_connect',compact('user_links','user'));
}
public function update_social(Request $request){
$user = $request->user();
$validator=Validator::make($request->all(),[
'facebook' => 'unique:social_links,facebook,'.$user->id,
'twitter' => 'unique:social_links,twitter'.$user->id,
'reddit' => 'unique:social_links,reddit,'.$user->id,
'google' => 'unique:social_links,google,'.$user->id
]);
if ($validator->fails()){
var_dump($user->id);exit;
return Redirect::back()->withErrors($validator)->withInput();
}
$data=Input::all();
$links = $user->links;
if ($links == null){
$links = new SocialLinks();
$links->fill($data);
$links->user_id=$user->id;
$links->save();
}else{
$links->fill($data);
$links->save();
}
return Redirect::back()->with('message','Your profile has been updated');
}
Update put validation logic in controller
this is what worked for me
$user = $request->user();
$id = $user->id;
$validator=Validator::make($request->all(),[
'facebook' => 'unique:social_links,facebook,'.$id.',user_id',
'twitter' => 'unique:social_links,twitter,'.$id.',user_id',
'reddit' => 'unique:social_links,reddit,'.$id.',user_id',
'google' => 'unique:social_links,google,'.$id.',user_id',
]);
I honestly don't get why though. Why do we concatenate id to exclude it from being validated? the syntax makes no sense to me. Also $id comes from user object, and 'user_id' is from my social links table. Am I matching ids here? Somebody please show me the light ;(
To start: In general, extending the Laravel Request class and dependency injecting your extended class into your controller functions, although it can be done, is a bad idea. Read this to understand why (although it may not appear to be related at first read):
Laravel 5 / Codeception not routing correctly
Basically the problem is that if your validation class throws a perfectly legitimate validation exception, that exception has to be trapped by the Laravel router and not by the controller function. Essentially unless the validation passes your controller function never gets called, and so it can't trap the validation exception. This frequently results in either a 500 error or a redirect to a completely different page (which is why this screws up codeception tests amongst other unwanted side-effects).
So a better plan is to pass a Laravel Request object into your controller function and validate inside the function, rather than attempting to get Laravel to do it for you.
Once you resolve that issue, getting the validation code to handle the case where the $user does not exist should be easy. Some suggestions for your validation code to handle that validation (which should now be inside your controller function, or in a separate validator class called from your controller function):
Request probably doesn't contain a User object. It might contain a user_id variable which you can turn into a User object using User::find($user_id) or similar.
Check to ensure that $user is not null before attempting to work with $user->id or you'll get an error. If the $user_id passed in is empty or invalid then User::find($user_id) will return null. Check for this case and throw an exception first, before you continue to look at $userId or save any links.
I can't see exactly what you're doing in your form but if the above doesn't resolve your issues then post the form here and we can take another look.
You need to edit validation for updating, this is my example from one app :
public function rulesAdmin($id = NULL)
{
return [
'name' => 'required|min:5',
'username' => 'unique:users' . ($id ? ",username, $id" : ''),
];
}
on editing ->you pass from database $id, on saving new record -> $id is NULL.
I followed a tutorial on Tutsplus about creating an ecommerce website using Laravel. The problem I'm having right now is when trying to route to a subfolder. In the tutorial, the instructor included a feature where you can view products by ID. And this is how he did it:
// StoreController.php
public function getView($id) {
return View::make('store.view')->with('store', Store::find($id));
}
This piece of code seems to be passing an id from the stores table. I think when a product is clicked, that's when the id is passed
// Routes.php
Route::controller('store', 'StoreController');
Also some of the templates:
// store\index.blade.php
<h2>Stores</h2>
<hr>
<div id="stores row">
#foreach($stores as $store)
<div class="stores col-md-3">
<a href="/store/products/view/{{ $store->id }}">
{{ HTML::image($store->image, $store->title, array('class' => 'feature', 'width'=>'240', 'height' => '127')) }}
</a>
<h3>{{ $store->title }}</h3>
<p>{{ $store->description }}</p>
</div>
#endforeach
</div><!-- end product -->
So.. How it goes is when I click on a product, it leads me to domain:8000/store/view/6 where 6 is the id.
This works fine but what I want to know is how do I route through a subfolder? Let's say I want it to be like this: store/view/products/6 considering that I have a folder called products and my view.blade.php is inside that like this: store/products/view.
In my StoreController class, I tried changing this
public function getView($id) {
return View::make('store.view')->with('store', Store::find($id));
}
to this
public function getView($id) {
return View::make('store.product.view')->with('store', Store::find($id));
}
but it does not seem to work giving me nothing but a Controller Method Not Found Error.
First, the view name View::make('store.product.view') has nothing to do with the URL.
You have to change the route:
Route::controller('store/view', 'StoreController');
And then adjust the name of your method in the controller because it should be the same as the segment of the URL after store/view
public function getProducts($id) {
return View::make('store.product.view')->with('store', Store::find($id));
}
I strongly recommend you read the Laravel docs on the topic
In my Laravel 4 project, I am trying to set a flash message when redirecting, like so:
return Redirect::route('main')->with('flash', 'Message here.');
(I looked at the following: Laravel 4 - Redirect::route with parameters).
The redirect happens properly. In my 'main' view I've got this code to display the flash message:
#if (Session::has('flash'))
<div class="flash alert">
<p>{{ Session::get('flash') }}</p>
</div>
#endif
But it doesn't work: Session::get('flash') returns an array, not a string. If I insert a call to var_dump(Session::get('flash')), I get this output:
array (size=2)
'new' =>
array (size=0)
empty
'old' =>
array (size=1)
0 => string 'flash' (length=5)
What is happening? It seems like fairly straightforward code...
When you redirect with data, the data you save will be 'flashed' into session (meaning it will only be available during the next request, see: http://laravel.com/docs/session#flash-data).
I would be wary of using 'flash' as a flash data key, as Laravel stores its flash data in a key already with a name of 'flash'. Try changing your name to something else. You may be confusing Laravel's Session::get as to where it should be attempting to load the data from.
Inside of the routes.php file try to create your routes within the
Route::group(['middleware' => ['web']], function () {
Route::get('/', [
'as' => 'home',
'uses' => 'PagesController#home'
]);
Route::resource('tasks', 'TasksController');
});
And After that use.
#if (Session::has('flash'))
<div class="flash alert">
<p>{{ Session::get('flash') }}</p>
</div>
#endif
Where you need to access session
I am building a practice app with the Laravel framework I built a form in one of the views which is set to post to the same view itself but when I hit submit the form is posted however I do not get the desired output, I see the original view again.
Here is my view index.blade.php
#extends('master')
#section('container')
<div class="wrapper">
{{ Form::open(array('url' => '/', 'method' => 'post')) }}
{{ Form::text('url') }}
{{ Form::text('valid') }}
{{ Form::submit('shorten') }}
{{ Form::close() }}
</div><!-- /wrapper -->
#stop
and my routes.php
Route::get('/', function()
{
return View::make('index');
});
Route::post('/', function()
{
return 'successfull';
});
What I've tried so far
I tried changing the post to a different view and it worked.
However I want the form to post to the same view itself.
Instead of returning a string I tried to return make a view still it
didn't work.
What am I doing wrong?
addendum
I see that when the form is making the post request I am getting a 301 MOVED PERMANENTLY HEADER
{{ Form::open(array('url' => ' ', 'method' => 'post')) }}
Passing a space as the url has worked for me.
I think this post: Form submits as GET Laravel 4 is related to your problem. I think the problem as I undersood it is caused by end a form url with a / . I found this when having problems to using post to a ./ url in my form. There is also a bug at github that seems like it is related https://github.com/laravel/framework/issues/1804.
I know this is an old question but I found this thread having the same problem so hopefully someone else is helped by my answer.
You need to make sure that your form's method does NOT end in a / for it to be routed correctly. For example if you have the following route:
Route::post('form/process', function()
{
# code here ...
});
Then you need to have the following form definition:
<form action="/form/process" method="POST">
I hope that helps.
I have same problem with OSx + MAMP, initially I've resolved with Raul's solution:
{{ Form::open(array('url' => ' ', 'method' => 'post')) }}
but after consultation with my friend we have concluded that my problem was due to the fact
my lavarel project is avaliable by long local path, as:
http://localhost/custom/custom2/...
in this location the post/get method on root path ("/") not working correctly.
Lavarel to working correctly must be avaliable by "vhost", in this case the problem get/post method on root location "/" not exist.
My friend advised me to use http://www.vagrantup.com/
BYE
There is some helpfull information in the Laravel Docs. Check these out:
Resource Controllers (or RESTful Controllers)
Forms & HTML
Opening A Form
Routing
Named Routes
I recommend you read the Resource Controllers documentation as it makes form handling a lot easier.
Well, you just return the view, so nothing change. You should bind your route to a controller to do some logic and add data to your view, like this:
index.blade.php
#extends('master')
#section('container')
<div class="wrapper">
#if (isset($message))
<p>{{$message}}</p>
#endif
{{ Form::open(array('url' => '/', 'method' => 'post')) }}
{{ Form::text('url') }}
{{ Form::text('valid') }}
{{ Form::submit('shorten') }}
{{ Form::close() }}
</div><!-- /wrapper -->
#stop
Your routes
Routes::any('/', 'home#index');
You controller HomeController.php
public function index()
{
$data = array();
$url = Input::get('url');
if ($url)
$data['message'] = "foo";
return View::make('index', $data);
}
You can also modify your current routes without using a controller like this (use the new view file)
Route::get('/', function()
{
return View::make('index');
});
Route::post('/', function()
{
return View::make('index')->with('message', 'Foo');
});
The problem is with defualt slashed in Apache from 2.0.51 and heigher:
http://httpd.apache.org/docs/2.2/mod/mod_dir.html#directoryslash
The best solution if you do not want to change Apache config is to make the post in a different path:
GOOD:
Route::get('/',
['as' => 'wizard', 'uses' => 'WizardController#create']);
Route::post('wizard-post',
['as' => 'wizard_store', 'uses' => 'WizardController#store']);
NOT GOOD:
Route::get('/',
['as' => 'wizard', 'uses' => 'WizardController#create']);
Route::post('/',
['as' => 'wizard_store', 'uses' => 'WizardController#store']);