Laravel Form validation redirects back to home page upon form errors instead of staying on same page - laravel

I have a contact form that when submitted, is successfully going to the DB. The issue is, when I check for validation on my webpage, the errors appear properly using Larvael $error validation, the problem is that my webpage always redirects back to home when errors show up instead of the page remaining still and showing the errors. I have to keep scrolling down to where my contact form is to see the errors; this will be annoying for my future users. How do I get the page to remain where it is if there are errors? NOTE: My page redirects correctly when the form is valid and submitted, this is not an issue. NOTE-2: I have created a single page webpage that the nav-links take you to, there are no redirects. Instead, it is one HTML page.
Web.php
Route::get('/', 'HomeController#index')->name('home');
Route::post('/contact/submit', 'MessagesController#submit');
MessagesController.php
namespace App\Http\Controllers;
use App\Message;
use Illuminate\Http\Request;
class MessagesController extends Controller
{
public function submit(Request $request)
{
$validatedData = $request->validate([
'name' => 'required|min:2',
'email' => 'required|max:255',
'phonenumber' => 'required|min:10|max:10',
'message' => 'required|min:5',
]);
Message::create($validatedData);
return redirect('/')->with('success', 'Your message has been
successfully sent. We will reach out to you soon');
}
}
contact.blade.php
{{--CONTACT FORM--}}
<section id="contact">
<div class="container-fluid padding">
<div class="row text-center padding">
<div class="col-12">
<h2 class="lead display-3">Contact Us</h2>
<hr class="my-4">
<form action="/contact/submit" method="POST">
#csrf
<div class="field">
<label for="name" class="label">Name</label>
<div class="control">
<input type="text" class="input {{$errors->has('name') ? 'is-danger' : 'is-success'}}"
name="name" placeholder="Project Title" value="{{old('name')}}">
</div>
</div>
<div class="field">
<label for="name" class="label">Email</label>
<div class="control">
<input type="text" class="input {{$errors->has('email') ? 'is-danger' : 'is-success'}}"
name="email" placeholder="Project Title" value="{{old('email')}}">
</div>
</div>
<div class="field">
<label for="name" class="label">Phone Number</label>
<div class="control">
<input type="text"
class="input {{$errors->has('phonenumber') ? 'is-danger' : 'is-success'}}"
name="phonenumber" placeholder="Project Title" value="{{old('phonenumber')}}">
</div>
</div>
<div class="field">
<label for="message" class="label">Message</label>
<div class="control">
<textarea name="message"
class="textarea {{$errors->has('message') ? 'is-danger' : 'is-success'}}"
placeholder="Project description">{{old('message')}}</textarea>
</div>
</div>
<div class="field">
<div class="control">
<button type="submit" class="button is-link">Create Project</button>
</div>
</div>
<!--Errors variable used from form validation -->
#if($errors->any())
<div class="notification is-danger">
<ul>
#foreach($errors->all() as $error)
<li>{{$error}}</li>
#endforeach
</ul>
</div>
#endif
</form>
</div>
</div>
</div>
</section>

You need to create a manual validator so that you have control over the redirect if the validation fails (which I assume is what you are having issues with).
public function submit(Request $request)
{
$validator = Validator::make($request->all(),[
'name' => 'required|min:2',
'email' => 'required|max:255',
'phonenumber' => 'required|min:10|max:10',
'message' => 'required|min:5',
]);
if ($validator->fails()) {
return redirect(url()->previous() .'#contact')
->withErrors($validator)
->withInput();
}
Message::create($request->all());
return redirect('/')->with('success', 'Your message has been
successfully sent. We will reach out to you soon');
}

First, move the errors to the top of the form so you can see them.
<form action="/contact/submit" method="POST">
#csrf
#if($errors->any())
<div class="notification is-danger">
<ul>
#foreach($errors->all() as $error)
<li>{{$error}}</li>
#endforeach
</ul>
</div>
#endif
A better way of handling validation is to separate it using a form request.
php artisan make:request SendMessageRequest
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class SendMessageRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'name' => 'required|min:2',
'email' => 'required|max:255',
'phonenumber' => 'required|min:10|max:10',
'message' => 'required|min:5',
];
}
}
If validation fails, a redirect response will be automatically generated to send the user back to their previous location.
Now update your controller.
use App\Http\Requests\SendMessageRequest;
use App\Message;
class MessagesController extends Controller
{
public function submit(SendMessageRequest $request)
{
Message::create($request->validated());
return redirect('/')->with('success', 'Your message has been
successfully sent. We will reach out to you soon');
}
}
You can leave the validation in your controller using the Validator and back() redirection, but the first is the better way.
public function submit(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|min:2',
'email' => 'required|max:255',
'phonenumber' => 'required|min:10|max:10',
'message' => 'required|min:5',
]);
if ($validator->fails()) {
return back()->withInput()->withErrors($validator);
}
Message::create($request->all());
return redirect('/')->with('success,' 'Your message has been
successfully sent. We will reach out to you soon');
}

Related

Can't upload files using livewire

I can't submit a form with file in order to proced to upload method, the file is selected when I submit it says that the file is required (empty data).
Everything works fine on mylocal Windows machine but I face the problem when using vps for production.
view :
<form wire:submit.prevent="submit" enctype="multipart/form-data">
<div>
#if(session()->has('message'))
<div class="alert alert-success">
{{ session('message') }}
</div>
#endif
</div>
<div class="form-group">
<label for="exampleInputName">Title:</label>
<input type="text" class="form-control" id="exampleInputName" placeholder="Enter title" wire:model="title">
#error('title') <span class="text-danger">{{ $message }}</span> #enderror
</div>
<div class="form-group">
<label for="exampleInputName">File:</label>
<input type="file" class="form-control" id="exampleInputName" wire:model="file">
#error('file') <span class="text-danger">{{ $message }}</span> #enderror
</div>
<button type="submit" class="btn btn-success">Save</button>
</form>
controller :
use WithFileUploads;
public $file, $title;
public function submit()
{
$validatedData = $this->validate([
'title' => 'required',
'file' => 'required',
]);
$validatedData['name'] = $this->file->store('files', 'public');
// File::create($validatedData);
session()->flash('message', 'File successfully Uploaded.');
}
VPS folders :
I tried to change permessions, user group.... no success.
try this
use WithFileUploads;
public $title;
public $file;
protected function rules()
{
return [
'title' => ['required', 'string', 'max:50'],
'file' => ['required', 'file', 'mimes:pdf,doc,docx', 'max:5000']
];
}
public function submit()
{
$this->validate();
$data = [
'title' => $this->title
];
if (!empty($this->file)) {
$url = $this->file->store('files', 'public');
$data['file'] = $url;
}
File::create($data);
session()->flash('message', 'File successfully Uploaded.');
}

Laravel: Display of validation errors not shown

I'm having a problem viewing validation errors in the blade view; this is the code below.
Controller (ClientController)
public function store(Request $request) {
$request->validate([
'name' => 'required',
'surname' => 'required',
'diagnosis' => 'required',
]);
Client::create([
'name'=>$request->name,
'surname'=>$request->surname,
'city'=>$request->city,
'diagnosis'=>$request->diagnosis,
]);
return redirect(route('client.index'))->with('message','The customer was successfully saved');
}
View (client.create)
<x-layout>
<div class="container">
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
<form action="{{route('client.store')}}" method="post">
#csrf
<div class="row mt-3">
<div class="col-12 col-md-6">
<div class="mb-3">
<label for="name" class="form-label">Nome</label>
<input type="text" class="form-control p-3" name="name" required>
</div>
<div class="mb-3">
<label for="surname" class="form-label">Cognome</label>
<input type="text" class="form-control p-3" name="surname" required>
</div>
<div class="col-12">
<div class="mb-3">
<label for="diagnosis" class="form-label">Diagnosi</label>
<input type="text" class="form-control p-3" name="diagnosis" required>
</div>
</div>
<button type="submit" class="btn btn-primary mb-5 py-3 px-5 mt-3 ms-3">Add</button>
</div>
</div>
</form>
</div>
</x-layout>
I have followed the documentation but am unable to understand where the problem is.
Laravel documentation
Thanks to those who will help me
CONTROLLER UPDATE:
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
return view('client.create');
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$request->validate([
'name' => 'required',
'surname' => 'required',
'diagnosis' => 'required',
]);
//dd($request->all());
Client::create([
'name'=>$request->name,
'surname'=>$request->surname,
'city'=>$request->city,
'diagnosis'=>$request->diagnosis,
'stay'=>$request->stay
]);
return redirect(route('client.index'))->with('message','The customer was successfully saved');
}
Index is a blade view that contains the customer table (this works fine).
The problem is the error messages I would like to see in the create view if an input is required and not compiled
So after checking all components, it has been under our nose the whole time.
All your inputs have the required attribute:
<div class="mb-3">
<label for="name" class="form-label">Nome</label>
<input type="text" class="form-control p-3" name="name" required>
</div>
<div class="mb-3">
<label for="surname" class="form-label">Cognome</label>
<input type="text" class="form-control p-3" name="surname" required>
</div>
<div class="col-12">
<div class="mb-3">
<label for="diagnosis" class="form-label">Diagnosi</label>
<input type="text" class="form-control p-3" name="diagnosis" required>
</div>
</div>
This way the request is not sent, because the browser actively needs to fulfil all requirements to start the request to client.create
If you would remove one of these attributes and then not fill it in and submit, it will cause the errors to show.
However, we concluded that it is better to keep the required attribute in, as it is better to prevent a call to the webserver than to only let laravel do the work of validation.
The laravel validation is more useful for ajax/api calls, where there is no frontend to prevent you from making the request, like this:
//required jquery
$.ajax({
url: '/your/url/here',
method: 'POST',
data: [
name: 'somename',
surname: 'somesurname',
],
success(response) {
console.log('Yay, it succeeded')
},
error(error) {
//I havent worked with jquery in a while, the error should be in error object
console.log(error);
}
})
Or how I like to do it in vue, with axios:
//requires axios
axios
.post('/url/here', {
surname: 'somesurname',
diagnosis: 'somediagnosis',
})
.then(response => {
console.log('Yay, it succeeded')
})
.catch(error => {
console.log('Error', error)
})
You can see in the last two examples, as there is no frontend to prevent this request from being made, you now at least make sure laravel is not going to run it's logic with missing variables, which would cause a crash.

POST method is not supported for this route

First, I've checked other question topic, but couldn't find the solution.
when I try to post my form. I am getting this error.
The POST method is not supported for this route. Supported methods:
GET, HEAD.
Form:
<div class="card-body">
<form action="{{route('profile.update', ['id' => $id])}}" method="post">
#csrf
#put
<div class="form-group">
<label for="location">Location</label>
<input class="form-control" type="text" name="location" value="{{$info->location}}">
</div>
<div class="form-group">
<label for="about">About</label>
<textarea name="about" id="about" rows="10" cols="50" class="form-control">{{$info->about}}</textarea>
</div>
<div class="form-control">
<p class="text-center">
<button class="btn btn-primary btn-md" type="submit">Update Your Info</button>
</p>
</div>
</form>
</div>
Routes:
Route::group(["middleware" => "auth"], function(){
route::get("/profile/edit", [
"uses" => "ProfilesController#edit",
"as" => "profile.edit"
]);
route::get("/profile/{slug}", [
"uses" => "ProfilesController#index",
"as" => "profile"
]);
route::put("/profile/update/{id}", [
"uses" => "ProfilesController#update",
"as" => "profile.update"
]);
});
in controller:
public function update(Request $request, $id)
{
dd($request->all());
}
From your question, i can understand that you're trying to update a profile using POST method or may be PUT method earlier. Since, the resource you are editing is unique, you're not passing any parameters for the controller to find that single resource so as to update it.
therefore modify your your route like
route::put("/profile/update/{id}", [
"uses" => "ProfilesController#update",
"as" => "profile.update"
]);
And your form like
<form action="{{route('profile.update', ['id' => $id])}}" method="post">
#csrf
#method('put')
You'll need to pass the ID of the profile you want to update as parameter
then at the controller
public function update(Request $request, $id){
//edit the profile with id = $id
}
You have an error in your form definition
<form class="{{route('profile.update', ['id' => $id])}}" method="post">
should be
<form action="{{route('profile.update', ['id' => $id])}}" method="post">
Since you made a form for PUT request, you have to change
route::post("/profile/update/profile", [
"uses" => "ProfilesController#update",
"as" => "profile.update"
]);
to this
route::put("/profile/update/profile", [
"uses" => "ProfilesController#update",
"as" => "profile.update"
]);
Here is the correction in your provided example.
In form route('profile.update', ['id' => {here you have to place id of record which you want to update}]).
View File
$info->id])}}" method="post">
<div class="form-group">
<label for="location">Location</label>
<input class="form-control" type="text" name="location" value="{{$info->location}}">
</div>
<div class="form-group">
<label for="about">About</label>
<textarea name="about" id="about" rows="10" cols="50" class="form-control">{{$info->about}}</textarea>
</div>
<div class="form-control">
<p class="text-center">
<button class="btn btn-primary btn-md" type="submit">Update Your Info</button>
</p>
</div>
</form>
</div>
In Route
Route::group(["middleware" => "auth"], function(){
route::get("/profile/{slug}", [
"uses" => "ProfilesController#index",
"as" => "profile"
]);
route::get("/profile/edit/profile", [
"uses" => "ProfilesController#edit",
"as" => "profile.edit"
]);
route::post("/profile/update/profile/{id}", [
"uses" => "ProfilesController#update",
"as" => "profile.update"
]);
});
In Controller
public function update(Request $request, $id)
{
dd($id, $request->all());
}

Email works with route using get request but email will not send with post request and there are no errors just a page refresh

I have verified emails are sending via mailgun with a public function mail using a get request with no data on the page. Trying to send an email from a contact page with a POST request simply refreshes the page with no errors but email does not send.
I have set the .env and config.mail / config.services and successfully send mail using a get request in web.php.
First I used Terminal php artisan make:mail. Then I created two routes for a contact page (GET / POST), created a contact view (works), send the data to PagesController.php, run a validation of the three inputs, pass the data to Mail::send. On click of submit button the page refreshes with no errors (validation not working) and email doesn't send.
PagesController.php:
Namespace(
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Post;
use App\Mail\Welcome;
use Mail;
class PagesController extends Controller
{
public function getContact(){
return view('pages/contact');
}
public function postContact(Request $request){
$this->validate($request,[
'email' => 'required|email',
'subject' => 'min:3',
'message' => 'min: 3'
]);
$data = array(
'email' => $request->email,
'subject' => $request->subject,
'bodyMessage' => $request->message
);
\Mail::send('email.Test', $data, function($message) use ($data){
$message->from($data['email']);
$message->to('visionquest.jesse#gmail.com');
$message->subject($data['subject']);
});
}
Web.php:
Route::get('contact', 'PagesController#getContact');
Route::post('contact', 'PagesController#postContact');
Test.blade.php:
<html>
<h1> Email from: {{ $email }}</h1>
<p> {{ $subject }} </p>
<br><br>
<hr>
<p>{{ $bodyMessage}}</p>
contact.blade.php:
#extends('main')
#section('title', '| Contact')
#section('content')
<div class="row">
<div class="col-md-12">
<h1>Contact Me</h1>
<hr>
<form acion="{{ url('contact') }}">
{{ csrf_field() }}
<div class="form-group">
<label name="email">Email:</label>
<input id="email" name="email" class="form-control">
</div>
<div class="form-group">
<label name="subject">Subject:</label>
<input id="subject" name="subject" class="form-control">
</div>
<div class="form-group">
<label name="message">Message:</label>
<textarea id="message" name="message" class="form- control">Type your message here...</textarea>
</div>
<input type="submit" value="Send message" class="btn btn-success">
</form>
</div>
</div>
#endsection
All I want to do is pull the information from the form and send it via email to a set address. I have been working on this for over week and now that I am not getting errors I have no idea what to do.
You can add this above the form in your blade file. You would be able to see the validation errors if any :
#if ($errors->any())
#foreach ($errors->all() as $error)
<div>{{$error}}</div>
#endforeach
#endif
Also change :
<form acion="{{ url('contact') }}">
To
<form action="{{ url('contact') }}" method="POST">
put some method on your form : method="POST" because once you will submit it, it will route to the GET route not the POST route since you did not declare a method on your form

Validation errors are not output and fields with previous Form data are not returned

Laravel 5.2
view where the form of sending data ('blade'):
#if( count($errors) > 0 )
<div class="alert alert-danger">
<ul>
#foreach( $errors->all() as $error ) <li>{{ $error }}</li> #endforeach
</ul>
</div>
#endif
<form method="POST" action="{{ route('contact') }}"> <!-- <?//='/contact');?> Or <?//=route('contact');?> -->
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="form-group">
<label for="name">Name:</label>
<input type="text" class="form-control" id="name" name="name" value="{{ old('name') }}" placeholder="Enter Name">
</div>
<div class="form-group">
<label for="email">Email address:</label>
<input type="email" class="form-control" id="email" name="email" value="{{ old('email') }}" placeholder="Enter E-mail">
</div>
<div class="form-group">
<label for="site">Site:</label>
<input type="text" class="form-control" id="site" name="site" value="{{ old('site') }}" placeholder="Enter Site">
</div>
<div class="form-group">
<label for="text_area">Text:</label>
<textarea class="form-control" id="text_area" name="text_area" rows="3" placeholder="Some text....."> {{ old('text_area') }} </textarea>
</div>
<div class="checkbox">
<label><input type="checkbox" name="checkbox"> Remember me</label>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div> <!--/class="col-"-->
</div> <!--/class="row"-->
ContactController.php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class ContactController extends Controller {
public function show( Request $request, $prm=false ){
$my_array = ['title1'=>'This variable `$title1` content', 'title2'=>'This variable `$title2` content', 'title3'=>'This variable `$title3` content']; //массив
$my_array2 = ['one'=>array('param1'=>'This variable `param1` content', 'param2'=>'This variable `param2` content', 'param3'=>'This variable `param3` content'),
'two'=>array('param4'=>'This variabl e `param4` content', 'param5'=>'This variable `param5` content', 'param6'=>'This variable `param6` content')
];
$my_array3 = array(
'title'=>'Contact',
'data'=>[ 'one'=>'list 1',
'two'=>'list 2',
'three'=>'list 3',
'four'=>'list 4',
'five'=>'list 5',
],
'dataI'=>['list-1','list-2','list-3','list-4','list-6','list-6'],
'bvar'=>true,
'script'=>"<script>alert('Hello! ++')</script>"
);
/** VALIDATION on Request */
if( $request->isMethod('post') ) {
$rules = [
'name' => 'required|max:10',
'email' => 'required|email',
//'site'=>'required',
//'text_area'=>'required',
];
$messages = [
'required' => 'The :attribute field is required.',
];
$this->validate($request, $rules, $messages);
dump( $request->all() );
dump( $request->session()->all() );
}
if( view()->exists('default.contact') ){
return view('default.contact')
->withMydata($my_array2)
->withMydata2($my_array)
->withMydata3($my_array3);
}
else { abort(404); }
}
}
/app/Http/Kernel.php
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
];
How can I see that validation fulfills and its rules are in effect,
But I do not see the display of validation errors when it is not passed and the data in the input fields when the Form is filled when redirecting back.
Let me show you my method which also uses validation on Laravel 5.2 and find out what the difference you have with this code:
The Controller which handles the request:
$validator = \Validator::make($request->all(), [
'data1' => 'required',
'data2' => 'required|in:bla1,bla2,bla3',
'data3' => 'required|array',
'data3.*' => 'required|json',
'data4' => 'required_if:data2,bla2',
]);
if ($validator->fails()) {
$request->flash();
return \Response::make(\View::make('theform')
->withErrors($validator)
->withInput($request->all())
->render()
, 406);
}
The form which contains the form which has been submitted and redrawn with error logs, named 'theform':
<input type="text" class="form-control" name="trip_name" id="trip_name"
placeholder="Gezi ismi" value="{{ old('trip_name') }}">
#if ($errors->has('trip_name'))
<span class="help-block">
<strong>{{ $errors->first('trip_name') }}</strong>
</span>
#endif
This is one way to show it. You can also view it your way as:
#if( count($errors) > 0 )
<div class="alert alert-danger">
<ul>
#foreach( $errors->all() as $error )
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
Well, the problem did not stop there ))
I create the validation through my own class Request and divide routes for GET and POST and defined separate methods for them in my Controller.
1. app/Http/routes.php
Route::get('/contact_form/{prm?}', ['uses'=>'Admin\ContactformController#show_form_get'])->name('contact_form');
Route::post('/contact_form', ['uses'=>'Admin\ContactformController#show_form_post']);
2. app/Http/Requests/ContactRequest.php - my custom Request class with validation rules:
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class ContactRequest extends Request
{
public function authorize()
{
return true; //false
}
public function rules()
{
return [
'name' => 'required|max:10',
//'name' => 'exists:users,name',
'email' => 'required|email',
'site'=>'required',
];
}
} //__/class ContactRequest
3. app/Http/Requests/ContactRequest.php - my Controller with POST and GET handling:
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Requests\ContactRequest; //custom Request class with validation rules
use App\Http\Controllers\Controller;
use \Illuminate\Support\Facades\Validator;
class ContactformController extends Controller {
public $show_controller_method = array(__METHOD__);
/** Method handler http-request with GET
*/
public function show_form_get( ){
$this->show_controller_method[] = 'showform()';
if( view()->exists('default.contact_form') ){
return view('default.contact_form')->withInfoMethodController($this->show_controller_method);
}
else { abort(404); }
} //__/public function show_form_get()
/** Method handler http-request with POST
*/
public function show_form_post( ContactRequest $request ){
if( $request->isMethod('post') ):
dump( $request->all() );
endif;
}
3. The view remained the same and there is a return of data "old inputs":
value="{{ old('name') }}" value="{{ old('email') }}" and so on...
and errors of validation if they exist:
#if( count($errors) > 0 )
<div class="alert alert-danger">
<ul>
#foreach( $errors->all() as $error ) <li>{{ $error }}</li> #endforeach
</ul>
</div>
#endif
Now the validation works (if it passes successfully - I see a dump() the POST.
If the validation falls, then a redirect occurs, but there are no validation errors and there are no old inputs.
Tell me please what I'm doing is not right?

Resources