405 Error when trying to send email via route with Laravel - php

Trying to send an email using Laravel but keep getting a 405 error and the whoops page showing:
* #param array $others
* #return void
*
* #throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
*/
protected function methodNotAllowed(array $others)
{
throw new MethodNotAllowedHttpException($others);
}
The code is:
{{ Form::open(array('url' => 'admin/newemail')) }}
// form items
{{ Form::close() }}
And the route is:
Route::get('admin/newemail', function()
{
$email = 'email#hotmail.com';
$data = array('s' => Input::get('email-heading'));
Mail::send('emails.wereback', $data, function($message) use ($email){
// $message details
});
});
However, if I directly go to the url admin/newemail it works fine.
Any help?

By default the Form helper will generate a html form that uses the POST method. You can specify the method if you need to use a different one:
{{ Form::open(array('url' => 'admin/newemail', 'method' => 'GET')) }}
Or you could also change your route to match POST requests:
Route::post('admin/newemail', function()
{
// [...]
});

Related

Can I validate form input also without using the laravelcollective/html namespace in a Laravel application?

I am pretty new in PHP and moreover in Laravel framework and I have the following doubt.
I am following this tutorial to insert a reCAPTCHA into a form (but my doubt is more related to form validation than to reCAPTCHA): http://tutsnare.com/how-to-use-captcha-in-laravel-5/
So to declare a form it use this syntax into the view:
{!! Form::open(array('url'=>'contact','method'=>'POST', 'id'=>'myform')) !!}
I think that this syntax is related to the laravelcollective/html namespace, is it?
So I have installed it performing the statment:
composer require "laravelcollective/html":"^5.4"
In the controller method is defined thisindex() method that handle the form sumbit operation:
<?php namespace App\Http\Controllers;
use Input;
use Validator;
use Redirect;
use Session;
class EnquiryController extends Controller {
public function index()
{
$data = Input::all();
$rules = array(
'name' => 'required',
'email' => 'required|email',
'subject' => 'required',
'g-recaptcha-response' => 'required|captcha',
'msg' => 'required',
);
$validator = Validator::make($data, $rules);
if ($validator->fails()){
return Redirect::to('/contact')->withInput()->withErrors($validator);
}
else{
// Do your stuff.
}
}
}
So, as you can see in the previous code snippet, this method provide input validation using the $rules array and if validation fails there is a redirect to the same page showing including the validation errors:
return Redirect::to('/contact')->withInput()->withErrors($validator);
that will be print in the view by this section of code:
#if (count($errors) > 0)
<div class="alert alert-danger">
<strong>Whoops!</strong> There were some problems with your input.<br /><br />
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
My doubt is: can I validate the form input and returns the potential errors in the same way also using the pure HTML form instead the one provided by the laravelcollective/html namespace?
Yes, also it's possible do more validation logic if you need it.
You can take approach for Form Request https://laravel.com/docs/5.4/validation#form-request-validation and some other validations.
Also, the after hook allow to evaluate before the rules define take place.
/**
* Configure the validator instance.
*
* #param \Illuminate\Validation\Validator $validator
* #return void
*/
public function withValidator($validator)
{
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('field', 'Something is wrong with this field!');
}
});
}
Yes you can validate by using normal html.
"laravelcollective/html": "~5.0"
Here is installation process: https://laravelcollective.com/docs/5.0/html
And Here is validation explanation: https://laravel.com/docs/5.0/validation#basic-usage
Thanks

Passing argument from controller to controller not working

Aloha, I'm making a workout manager in which you have a dashboard displaying your 5 last workouts. I have set a form for each one workout for allowing the user to delete any of them. Here the form in the dashboard:
{!! Form::open(['route' => ['dashboard.workout.destroy', $workout->id], 'style' =>'display:inline-block;', 'method' => 'DELETE']) !!}
This route will call this method in WorkoutController.php
public function destroy($id, Request $request)
{
$workout = Workout::findOrFail($id);
$workout->delete();
$message = "Workout deleted successfully!";
return redirect()->route('dashboard.index', ['message' => $message]);
}
And this route will call this method in DashboardController.php
public function index($message = null)
{
$user = Auth::user();
// Workouts
...
// Inbodies
...
// Measures
...
return view('dashboard.index', compact('user','workoutsDesc','workouts','lastInbody','inbodies','measures','lastMeasure','message'));
}
The question is that I'm trying to pass the variable $message from WorkoutController to DashboardController for displaying a successfull alert after deleting a workout, but I don't know how to do it. I have tried with:
return redirect()->action('Dashboard\DashboardController#index', [$message]);
return redirect()->action('Dashboard\DashboardController#index')->with('message', $message);
return redirect()->route('dashboard.index', $message);
But I still trying to find the way for doing it.
First of all, from Laravel 5.1 Documentation:
If your route has parameters, you may pass them as the second argument to the route method
As the message is not a parameter to your route, so you can't pass that. A possible solution can be Flashing data. Check the next controller if the session has that key and contain a value, then add it to a variable and pass to the view.
Hope this works.

How do you flash Request data if a Validator fails in Laravel 5?

I've created a simple contact form in Laravel 5, using the Request object and a Validator object to check my input for errors.
The form in my view is coded in HTML, rather than the Laravel Form object, which isn't included by default in Laravel 5.
I need to set up my form so that if a validation rule fails, the user's input is flashed to the session so it doesn't disappear when the page redirects. I was able to accomplish this by putting a $request->flash() in the POST controller, before the validation code.
However, I do not want the data to be flashed (i.e, the form should be reset) if the validation passes and the form is successfully emailed. There's no apparent way for me to accomplish this in the $this->validate block, since Laravel helpfully handles the redirects automatically.
How can I tell Laravel to flash the form data ONLY if there is a validation error?
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class ContactController extends Controller
{
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
return view('contact');
}
/**
* Store a newly created resource in storage.
*
* #param Request $request
* #return Response
*/
public function store(Request $request)
{
// Flash current input in case the validator fails and redirects
$request->flash();
// Validate the form request, redirect on fail
$this->validate($request, [
'name' => 'required',
'email' => 'required|email',
'subject' => 'required',
'message' => 'required|min:5',
]);
// Generate email from template and send
\Mail::send('emails.feedback',
array(
'name' => $request->get('name'),
'email' => $request->get('email'),
'user_message' => $request->get('message'),
'subject' => $request->get('subject')
), function ($message) use ($request) {
$message->from(\Config::get('site.from_email'));
$message->to(\Config::get('site.contact_email'), 'Admin');
$message->subject(\Config::get('site.name') . ': ' . $request->get('subject'));
});
// Redirect to Contact route with success message
return \Redirect::route('contact')
->with('message', 'Thanks for contacting us!');
}
}
?>
If anybody like me didn't know how to get the old values and end up here somehow, here it goes:
<input value="{{ old('var_name') }}">
I don't see you needing to access the session data when Laravel provides you helpers like this.
Hope to have helped, have a nice day. =)
Just remove the following line of code:
$request->flash();
Laravel will take care of that for you by flashing the data on failed validation. The following method gets called on failed validation:
/**
* Create the response for when a request fails validation.
*
* #param \Illuminate\Http\Request $request
* #param array $errors
* #return \Illuminate\Http\Response
*/
protected function buildFailedValidationResponse(Request $request, array $errors)
{
if ($request->ajax() || $request->wantsJson()) {
return new JsonResponse($errors, 422);
}
return redirect()->to($this->getRedirectUrl())
->withInput($request->input()) // <-- Flashes inputs
->withErrors($errors, $this->errorBag()); // <-- Flashes errors
}
This is the trait used in your controller for validating the request and it's located at Illuminate/Foundation/Validation, name is ValidatesRequests. Check it to clarify yourself.
Alternatively, you may do it manually if you want for any reason, check the documentation.
To restore the old value if validation fails the entered data will display the view
value="{{ (old('title')) ? old('title') : $data->title}}

Render controller in TWIG and show form errors

I have indexAction and contactAction
contactAction is a simple form with no mapped fields (FormType) like below:
/**
* #Route("/contact", name="contact")
* #Template()
* #param Request $request
* #return array
*/
public function contactAction(Request $request)
{
$form = $this->createForm(new ContactType());
$form->handleRequest($request);
if ($form->isValid()) {
$firstName = $form->get('first_name')->getData();
$lastName = $form->get('last_name')->getData();
$email = $form->get('email')->getData();
$message = $form->get('message')->getData();
}
return array(
'form' => $form->createView()
);
}
and i render this form in my indexAction with this TWIG command:
{{ render(controller('RusselBundle:Default:contact')) }}
Everything is okey, if page is not reloaded, HTML5 validators works fine, but if form have some errors like: firstName length, error's not show at all, how can i do, so that errors showed up in the form indexAction? Any help would be appreciated. I'm just curious it's possible, and if - how ? Sorry for my english....
Rather than using the request passed into the action you should get the master request from the request stack. As #DebreczeniAndrás says, when you use the render(controller()) you are using a newly created sub-request rather than the request that was actually passed to the page on load (the master request).
public function contactAction(Request $request)
{
$request = $this->get('request_stack')->getMasterRequest();
$form = $this->createForm(new ContactType());
//...
}
On symfony3 use render function like this
{{ render(controller('RusselBundle:Default:contact', {'request':app.request})) }}
If you use the render function in your twig, then that creates a subrequest, thus your original posted (i.e. in your main request) values get lost.
You can pass your main request to your form render action as follows:
{{ render(controller('RusselBundle:Default:contact'), 'request' : app.request ) }}
This will pass all the main request parameters appropriately to your subrequest.

Laravel 4 Authentication: Reminders Controller - GET reset not found

I am using Laravel 4's built in password reminder feature in a new application. It seems that the code it's generating and what the docs are saying is either incomplete, inconsistent, or I'm missing a vital point.
So far, I have...
Created Reminder Table
Migrated it
Created Reminder Controller
Tested both get / post for password/remind, successfully.
Where I am stuck is with the reset methods of the controller. The reminder url successfully sends to my email and once I click it, I get a Symfony \ Component \ HttpKernel \ Exception \ NotFoundHttpException error.
The url that the Password::remind static method sends to my email is http://localhost/application/public/password/reset/3e5e7a5c8562b28909b9948e848c5692dccb4f8a.
My GET / POST reset methods in the reminder controller -
public function getReset($token = null)
{
if (is_null($token)) App::abort(404);
return View::make('password.reset')->with('token', $token);
}
public function postReset()
{
$credentials = Input::only(
'email', 'password', 'password_confirmation', 'token'
);
$response = Password::reset($credentials, function($user, $password)
{
$user->password = Hash::make($password);
$user->save();
});
switch ($response)
{
case Password::INVALID_PASSWORD:
case Password::INVALID_TOKEN:
case Password::INVALID_USER:
return Redirect::back()->with('error', Lang::get($response));
case Password::PASSWORD_RESET:
return Redirect::to('/');
}
}
My password/reset.blade.php file -
{{ Form::open(array('url' => 'password/reset')) }}
{{ Form::hidden('token', $token) }}
{{ Form::email('email', null, array('class'=>'', 'placeholder'=>'Email Address')) }}
{{ Form::password('password', array('class'=>'', 'placeholder'=>'Password')) }}
{{ Form::password('password_confirmation', array('class'=>'', 'placeholder'=>'Password Confirmation')) }}
{{ Form::submit('Reset Password', array('class'=>'')) }}
{{ Form::close() }}
Anyone have any ideas as to where I'm going wrong??
Your most likely missing some routes add these if they don't already exist.
Route::get('password/reset/{token}', 'RemindersController#getReset');
It is also likely that you will need the reset post route as well.
Route::post('password/reset/{token}', 'RemindersController#postReset');

Categories