I've got a form on a Laravel 5.2 application that uses form request validation. When I submit a request and the validator rejects it it goes back to the form and displays the validator's errors. All the user inputs are still there except for the fields that have multi-select, they are cleared. I don't want them cleared, I want them to display what the user had intended.
I'm having a hell of a time trouble shooting this because my localhost version works fine. This problem only occurs on the production version of the application.
Here is the issue request:
class IssueRequest 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()
{
$rules = [
'do' => 'required|date_format:"F d, Y"',
'issue_advocate' => 'required',
'issue_type_list' => 'required',
'file_stale_date' => 'date_format:"F d, Y"',
'level_of_service_list' => 'required_with:staff_hours',
'issue_outcome_list' => 'required_with:staff_hours',
'staff_hours' => 'numeric',
'date_closed' => 'date_format:"F d, Y"'
];
return $rules;
}
public function messages(){
return [
'issue_type_list.required' => 'Please select at least one issue type.',
'do.required' => 'The date opened field is required.',
'date_format' => 'The :attribute needs to be in the format "January 1, 2000".',
'issue_outcome_list.required_with' => 'Please select at least one outcome before entering staff hours (this marks the issue to be closed)',
'level_of_service_list.required_with' => 'Please select at least one level of service before entering staff hours (this marks the issue to be closed)',
];
}
}
Here is an excerpt of the form. The fields of concern are the issue_type_list, level_of_service_list and issue_outcome_list:
{!! Form::model($issue, array('method' => 'PATCH', 'url' => 'issues/'.$issue->id)) !!}
#include('issues.addIssueForm')
<div class="form-group">
{!! Form::label('issue_type_list[]', "Issue Type") !!}
{!! Form::select('issue_type_list[]', $issuetypes, null, ['multiple' => 'multiple', 'class' => 'form-control multi-select', 'id' => 'issue_type']) !!}
#if($errors->first('issue_type_list'))
<div class="error-item alert alert-danger">{{ $errors->first('issue_type_list') }}</div>
#endif
</div>
{!! Form::hidden('client_id',Input::get('client_id')) !!}
<div class="form-group">
{!! Form::label('level_of_service_list[]', "Level of Service") !!}
{!! Form::select('level_of_service_list[]', $level_of_service, null, ['multiple' => 'multiple', 'class' => 'form-control multi-select', 'id' => 'level_of_service']) !!}
</div>
#include('issues.referralForm')
<div class="form-group">
{!! Form::label('issue_outcome_list[]', "Outcome") !!}
{!! Form::select('issue_outcome_list[]', $outcome, null, ['multiple' => 'multiple', 'class' => 'form-control ']) !!}
</div>
<div class="form-group">
{!! Form::label('staff_hours', "Staff hours") !!}
{!! Form::input('number', 'staff_hours', null, ['class' => 'form-control', 'min'=>'0', 'step' => '0.1']) !!}
</div>
<div class="form-group">
{!! Form::submit('Edit Issue', ['class' => 'btn btn-primary form-control']) !!}
Cancel
</div>
{!! Form::close() !!}
Related
Im trying to use a form to submit reviews for products but I believe the submit button uses the incorrect controller store method. I have a controller for products and one for reviews. The products store works correctly and I can see the database being populated once submitted however when I go to submit a review for a product it will throw the custom error messages from the product store form. If I change the reviews form::open to the products form::open it will throw an error: The PUT method is not supported for this route. Supported methods: GET, HEAD, POST.
Products form (works properly)
{!! Form::open(['action' => 'App\Http\Controllers\ProductsController#store', 'method' => 'POST', 'enctype' => 'multipart/form-data']) !!}
... labels and text ...
{{ Form::submit('Submit', ['class' => 'btn btn-primary']) }}
{!! Form::close() !!}
Reviews form
<div>
<p>Write a review</p>
<!-- submit review form -->
{!! Form::open(['reviews' => 'App\Http\Controllers\ReviewsController#store']) !!}
<div class="form-group">
{{ Form::textarea('description', '', ['class' => 'form-control', 'placeholder' => 'Write your message']) }}
</div>
<div class="form-group">
{{ Form::label('rating', 'Rating') }}
{{ Form::select('rating', ['1' => '1', '2' => '2', '3' => '3', '4' => '4', '5' => '5'], '1') }}
</div>
{{ Form::hidden('_method', 'PUT') }}
{{ Form::submit('Submit', ['class' => 'btn btn-primary']) }}
{!! Form::close() !!}
</div>
ReviewsController store
public function store(Request $request, $id)
{
$this->validate($request, ['description' => 'nullable',
'rating' => 'nullable',
]);
$review = new Review;
$review->rating = $request->input('rating');
$review->reviewerid = auth()->user()->id;
$review->productid = $id;
$review->description = $request->input('description');
$review->save();
return redirect('/products/$id')->with('success', 'Review submitted');
}
Web.php file
Route::get('/', 'App\Http\Controllers\PagesController#index');
Route::get('/about', 'App\Http\Controllers\PagesController#abouts');
Route::get('/cart', 'App\Http\Controllers\PagesController#cart');
Route::get('/checkout', 'App\Http\Controllers\PagesController#checkout');
Route::get('/dashboard', 'App\Http\Controllers\PagesController#services');
Route::get('/categories/{Category}', 'App\Http\Controllers\PagesController#category');
Route::resource('reviews', 'App\Http\Controllers\ReviewsController');
Route::resource('products', 'App\Http\Controllers\ProductsController');
Auth::routes();
The error is because of this line:
Form::hidden('_method', 'PUT')
You're telling laravel to use put method. Delete it and it will work fine.
For your form action, I think you have type in this line:
{!! Form::open(['reviews' => 'App\Http\Controllers\ReviewsController#store']) !!}
Change it to :
{!! Form::open(['action' => 'App\Http\Controllers\ReviewsController#store']) !!}
Trying to delete entries using the destroy method in Laravel controller.
public function destroy($id)
{
$university = University::find($id);
$university->delete();
return redirect('/universities');
}
And this is what i'm using in the view
{!!Form::open(['action' => ['UniversityController#destroy', $university->Id], 'method' => 'POST'])!!}
{{Form::hidden('_method', 'DELETE')}}
{{Form::submit('Delete', ['class' => 'btn btn-danger'])}}
{!!Form::close()!!}
Getting no errors and browser redirects after the button is activated as instructed, but the entry still remains in the veiw list and in the DB. Using MySQL.
Posting to the DB also works fine, but having same problems with update method. No errors and get redirected as I should but no update has happened.
public function update(Request $request, $id)
{
$this->validate($request, [
'Name' => 'required',
'Country' => 'required'
]);
$university = University::find($id);
$university->Name = $request->input('Name');
$university->Country = $request->input('Country');
$university->save();
return redirect('/universities');
}
And in view:
{!! Form::open(['action' => ['UniversityController#update', $university->Id], 'method' => 'POST']) !!}
<div class="form-group">
{{Form::label('Name', 'Name')}}
{{Form::text('Name', $university->Name, ['class' => 'form-control', 'placeholder' => 'Name'])}}
</div>
<div class="form-group">
{{Form::label('Country', 'Country')}}
{{Form::text('Country', $university->Country, ['class' => 'form-control', 'placeholder' => 'Country'])}}
</div>
{{Form::hidden('_method', 'PUT')}}
{{Form::submit('Submit', ['class' =>'btn btn-primary'])}}
{!! Form::close() !!}
Also tried running without the hidden form methods, but same result.
My routes:
Route::get('/universities', 'UniversityController#index');
Route::get('/universities/create', 'UniversityController#create');
Route::get('/universities/{id}/edit', 'UniversityController#edit');
Route::put('/universities/{id}', 'UniversityController#update');
Route::post('/universities/create', 'UniversityController#store');
Route::delete('/universities/{id}', 'UniversityController#destroy');
Solved by setting public $primaryKey = 'Id'; in the model.
I made form with select. Here is code:
{!! Form::model($customerAccount, ['route' => ['admin.customerAccount.update',
$customerAccount->id_customer_account], 'method' => 'PUT', 'class' => 'form-horizontal']) !!}
...
<div class="#if ($errors->has('cacct_active'))has-error has-feedback #endif form-group">
{!! Form::label('cacct_active', 'Status: *',['class' => 'col-md-4 control-label']) !!}
<div class="col-md-8">
{!! Form::select('cacct_active',$customerAccount->getStatusList(),null,['class'=>
'form-control', 'required' => 'required', 'autofocus' => 'none']) !!}
</div>
</div>
I have options loaded by $customerAccount->getStatusList() and want default selected option to be value from my object. But it does not happen, selected is just the first one from options.
EDIT
the problem was I was using 'true, false' values in db and then '0, 1' values in 'statusList' parameter - the easiest way to solve this was to use mutator 'casts' in model for this field
I am trying to set up a contact form on a one page site using laravel, I can't seem to be able to get the form to validate the user input and show any errors that the form might have.
email.blade.php:
<ul>
#foreach($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
{!! Form::open(['route' => 'mail', 'method' => 'post', 'role' => 'form', 'id' => 'footer-form']) !!}
<div class="form-group has-feedback">
{!! Form::label('first_name', null, ['class' => 'sr-only']) !!}
{!! Form::text('first_name', null, ['class' => 'form-control', 'placeholder' => 'First Name']) !!}
<i class="fa fa-user form-control-feedback"></i>
#if($errors->has('first_name'))
{{ $errors->first('first_name') }}
#endif
</div>
<div class="form-group has-feedback">
{!! Form::label('last_name', null, ['class' => 'sr-only']) !!}
{!! Form::text('last_name', null, ['class' => 'form-control', 'placeholder' => 'Last Name']) !!}
<i class="fa fa-user form-control-feedback"></i>
#if($errors->has('last_name'))
{{ $errors->first('last_name') }}
#endif
</div>
<div class="form-group has-feedback">
{!! Form::label('email', null, ['class' => 'sr-only']) !!}
{!! Form::email('email', null, ['class' => 'form-control', 'placeholder' => 'Email address']) !!}
<i class="fa fa-envelope form-control-feedback"></i>
#if($errors->has('email'))
{{ $errors->first('email') }}
#endif
</div>
<div class="form-group has-feedback">
{!! Form::label('textarea', null, ['class' => 'sr-only']) !!}
{!! Form::textarea('textarea', null, ['class' => 'form-control', 'rows' => 8, 'placeholder' => 'Message']) !!}
<i class="fa fa-pencil form-control-feedback"></i>
#if($errors->has('textarea'))
{{ $errors->first('textarea') }}
#endif
</div>
{!! Form::submit('Send', ['class' => 'btn btn-default']) !!}
{!! Form::close() !!}
Route: web.php:
Route::get('/ensignhospital', [
'as' => 'home',
'uses' => 'HomeController#home'
]);
Route::group(['before' => 'guest'], function () {
/*
* CSRF Protection
*
* */
Route::group(['before' => 'csrf'], function () {
Route::post('/ensignhospital', [
'as' => 'mail',
'uses' => 'HomeController#postSendMail'
]);
});
});
controller to handle for request:
class HomeController extends Controller {
public function home(){
return View('welcome');
}
public function postSendMail(ContactFormRequest $request){
if($request->fails()){
return Redirect::route('')
->withErrors()
->withInput();
}else{
return View('passed');
}
}
}
The form request validator class:
class ContactFormRequest 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 [
//
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required|email',
'message' => 'required'
];
}
}
Problem the form does not validate when I don't enter a valid input. I need the form to validate user input and remain at the form position on the web page.
please note:
I used a .htaccess file to get the site which is on my computer to display the site root as localhost/mylaravelproject rather than the usual localhost/mylaravelprojec/public that one will normally see on a fresh install of laravel.
From the documentation here: https://laravel.com/docs/5.3/validation#form-request-validation
So, how are the validation rules evaluated? All you need to do is type-hint
the request on your controller method. The incoming form request is validated
before the controller method is called, meaning you do not need to clutter
your controller with any validation logic.
Laravel will never actually remain on the form. It will instead redirect, validate and then redirect back, with the errors. You do not need the check in your code if($request->fails()).
So my create news form is very simple:
<div class="row padding-10">
{!! Form::open(array('class' => 'form-horizontal margin-top-10')) !!}
<div class="form-group">
{!! Form::label('title', 'Title', ['class' => 'col-md-1 control-label padding-right-10']) !!}
<div class="col-md-offset-0 col-md-11">
{!! Form::text('title', null, ['class' => 'form-control']) !!}
</div>
</div>
<div class="form-group">
{!! Form::label('body', 'Body', ['class' => 'col-md-1 control-label padding-right-10']) !!}
<div class="col-md-offset-0 col-md-11">
{!! Form::textarea('body', null, ['class' => 'form-control']) !!}
</div>
</div>
<div class="col-md-offset-5 col-md-3">
{!! Form::submit('Submit News', ['class' => 'btn btn-primary form-control', 'onclick' => 'this.disabled=true;this.value="Sending, please wait...";this.form.submit();']) !!}
</div>
{!! Form::close() !!}
This is processed by NewsProvider:
public function store()
{
$validator = Validator::make($data = Input::all(), array(
'title' => 'required|min:8',
'body' => 'required|min:8',
));
if ($validator->fails())
{
return Redirect::back()->withErrors($validator)->withInput();
}
News::create($data);
return Redirect::to('/news');
}
But i have another field, not only title and text body in database, which is author_id and I have no idea how to add info, like the user id from currently authenticated user which wasnt supplied by form. I know how to add hidden input to form with user id, but then someone could change hidden field value. How do I do that correct way?
Maybe I have to edit my news eloquent model in some way, which is:
use Illuminate\Database\Eloquent\Model as Eloquent;
class News extends Eloquent {
// Add your validation rules here
public static $rules = [
'title' => 'required|min:8',
'body' => 'required|min:8',
];
// Don't forget to fill this array
protected $fillable = array('title', 'body');
}
You can always get the current authenticated user by Auth::user(). And you can also modify the $data array before passing it to create. Here's how you do it:
$data['author_id'] = Auth::user()->id;
News::create($data);
Also don't forget to add author_id to the fillable attributes
protected $fillable = array('title', 'body', 'author_id);