Laravel post error - laravel

I'm getting the following error message when trying to update user data:
protected function methodNotAllowed(array $others)
{
throw new MethodNotAllowedHttpException($others);
}
I'm logging the user in, then want to give them the option to change their preferences. The form displays fine in the view but won't post.
Here are my routes:
Route::prefix('admin')->group(function(){
Route::get('/login', 'Auth\AdminLoginController#showLoginForm')->name('admin.login');
Route::post('/login', 'Auth\AdminLoginController#login')->name('admin.login.submit');
Route::get('/', 'AdminsController#index')->name('admin.dashboard');
Route::post('/', 'AdminsController#update')->name('admin.dashboard.update');
Route::get('/logout', 'Auth\AdminLoginController#logout')->name('admin.logout');
Here's the Controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Admin;
use Auth;
class AdminsController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth:admin');
}
/**
* Show the application dashboard.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$id = Auth::user()->id;
$admin = Admin::find($id);
return view('admin')->with('admin',$admin);
}
public function update(Request $request, $id)
{
$this-> validate($request, [
'target_sector' => 'required|max:255',
'target_skillsets' => 'required|max:255',
'target_companies'=> 'required|max:255',
'target_locations'=> 'required|max:255',
]);
//Create Post
$id = Auth::user()->id;
$admin = Admin::find($id);
$admin->target_sector = $request->input('target_sector');
$admin->target_skillsets = $request->input('target_skillsets');
$admin->target_companies = $request->input('target_companies');
$admin->target_locations = $request->input('target_locations');
$admin->save();
return redirect('/admin')->with('success', 'Preferences Updated', 'admin',$admin);
}
}
And here is the view:
#include('includes.nav_login')
#extends('layouts.app')
#section('content')
<div class="container">
<div class="row mt-4">
<div class="col-md-10 offset-md-1">
<div class="card">
<div class="card-header">Admin Dashboard</div>
<div class="card-body">
#if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
#endif
You are logged in as ADMIN!
</div>
<div class="card-header">Update Vacancy Preferences</div>
<div class="card-body">
{!! Form::open(['action' => ['AdminsController#update', $admin], 'method' => 'POST']) !!}
<div class="form-group">
{{Form::label('companies', 'Companies')}}
{{Form::text('companies', $admin->target_companies,['class'=>'form-control', 'placeholder'=>'Target Companies'])}}
</div>
<div class="form-group">
{{Form::label('skillsets', 'Skillsets')}}
{{Form::text('skillsets', $admin->target_skillsets,['class'=>'form-control', 'placeholder'=>'Skillsets'])}}
</div>
<div class="form-group">
{{Form::label('sector', 'Sector')}}
{{Form::text('sector', $admin->target_sector,['class'=>'form-control', 'placeholder'=>'Sector'])}}
</div>
<div class="form-group">
{{Form::label('locations', 'Locations')}}
{{Form::text('locations', $admin->target_locations,['class'=>'form-control', 'placeholder'=>'Locations'])}}
</div>
{{Form::hidden('_method', 'PUT')}}
{{Form::submit('Update',['class'=>'btn btn-primary'])}}
{!! Form::close() !!}
</div>
</div>
</div>
</div>
</div>
#endsection
Can anyone explain why this isn't working?

You should fix you route, because you are using put method for update, but on routes, you defined as post
Route::post('/', 'AdminsController#update')->name('admin.dashboard.update');
Therefore error occurs.
You should fix your route like this,
Route::put('/{id}', 'AdminsController#update')->name('admin.dashboard.update');
I hope this help you.

The error says MethodNotAllowed which means you are hitting a route with a different request method than it accepts
you open the form like this
{!! Form::open(['action' => ['AdminsController#update', $admin], 'method' => 'POST']) !!}
so till now the form method is POST
but then you spoof the method to be of type put
{{Form::hidden('_method', 'PUT')}}
so now the method becomes of type put not post
however your route expects the method to be post
Route::post('/', 'AdminsController#update')->name('admin.dashboard.update');
This is why you get method not allowed exception
you either change the method on your controller to be put instead of post or remove the method spoofing thing from inside your form
I mean this line
//remove this
{{Form::hidden('_method', 'PUT')}}
once you fix it you will have another error because you don't have csrf field in your form so just add this inside of your form
#csrf

Really appreciate both answers on here - thanks #Mohammad Instanboli and #webdevtr.
Webdevtr was right to advise this:
Route::put('/{id}', 'AdminsController#update')->name('admin.dashboard.update');
I also had to go back and fix the following which I thought would be useful to note if anyone else views this with a similar issue:
Firstly my AdminsController#update method needed the following changes:
I changed the public function update to take one less variable - ($id)
public function update(Request $request)
{
$this-> validate($request, [
'target_sector' => 'required|max:255',
'target_skillsets' => 'required|max:255',
'target_companies'=> 'required|max:255',
'target_locations'=> 'required|max:255',
]);
//Create Post
$id = Auth::user()->id;
$admin = Admin::find($id);
$admin->target_sector = $request->input('target_sector');
$admin->target_skillsets = $request->input('target_skillsets');
$admin->target_companies = $request->input('target_companies');
$admin->target_locations = $request->input('target_locations');
$admin->save();
return redirect('/admin')->with('success', 'Preferences Updated', 'admin',$admin);
}
Then I needed to make sure the $request->input('x') matched the input names in the form in my view - i.e:
<div class="form-group">
{{Form::label('target_sector', 'target_sector')}}
{{Form::text('target_sector', $admin->target_sector,['class'=>'form-control', 'placeholder'=>'Sector'])}}
</div>

Related

How to insert data with logged in user id? Laravel-6

I want to submit data to bidding table with logged in user id and auction id from product show method.
This is how my tables are in relation.
Is it good to use ProductController or should I create another controller for bidding table?
Product show blade
#extends('layouts.app')
#section('content')
<div class="container">
<div class="my-3 border">
<div class="row">
<div class="col-md-5">
<img src="/storage/images/{{$product->image}}" alt="" style="width: 100%;">
</div>
<div class="col-md-7">
<h2>{{$product->name}}</h2>
<p>{{$product->description}}</p>
<span>Category: {{$product->category->name}}</span><br>
<span class="text-right">Auction Ends: {{$product->auction->deadline}}</span>
<div class="price">Initial Price: {{$product->price}}</div>
{!! Form::open(['action' => 'BiddingsController#create', 'method' => 'POST', 'enctype' => 'multipart/form-data']) !!}
<div class="form-inline">
{{Form::number('bidamount', '',['class' => 'form-control mr-1', 'placeholder' => 'Place your bid'])}}
{{Form::submit('Place Bid', ['class' => 'btn btn-primary'])}}
</div>
{!! Form::close() !!}
#endsection
Bidding controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Bidding;
class BiddingsController extends Controller
{
public function index()
{
$biddings = Bidding::all();
return view('products.show' ,compact('biddings', $biddings));
}
public function create()
{
//
}
public function store(Request $request)
{
//
}
public function show(Bidding $bidding)
{
//
}
}
In a Laravel 6 app, you can get the Logged in user using the auth() helper.
$authUser = auth()->user();
Doc: https://laravel.com/docs/6.x/helpers#method-auth
Cordially
You can check anytime your logged details by Auth!
Everywhere and from anywhere you can use Auth::user()->id;
example:
for getting logged user id in controller check by!
dd(Auth::user()->id);
If needed just use Illuminate\Support\Facades\Auth in the very beginning of controller.

Laravel problems with redirect

So I am working on a laravel project and I want that if a user types in their order code, the order will show up with the details. For some reason, the order code doesn't get through the if statement, because I get the output 'Order not found.' all the time, even if I type in an order code that is present in my orders table.
TrackController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Order;
class TrackController extends Controller
{
public function index()
{
return view ('track.index');
}
public function show($id)
{
$order = Order::where('code', $id)->first();
return view('track.show',[
'order' => $order
]);
}
public function redirect(Request $request)
{
$orderCode = $request->input('order-track-id');
$order = Order::where('code', $orderCode)->first();
if(!$order){
return redirect('/track')->with('error', 'Order not found.');
}else{
return redirect('/track/' . $order->code);
}
}
}
web.php
Route::get('/track', 'TrackController#index');
Route::post('/track/redirect', 'TrackController#redirect');
Route::get('/track/{id}', 'TrackController#show');
track.index
#extends('layouts/app')
#section('content')
<div class="container">
<div class="row justify-content center">
{!! Form::open(['action' => 'TrackController#redirect', 'method' => 'post']) !!}
{!! csrf_field() !!}
<input type="number" name="input-order-track-id" id="order-track-id">
{{ Form::button('Track', ['type' => 'submit', 'class' => 'btn btn-primary'] ) }}
{!! Form::close() !!}
</div>
</div>
#endsection
What am I doing wrong and why isn't my function putting me through to the show function in the TrackController?
In your redirect controller function.
public function redirect(Request $request)
{
$orderCode = $request->input('input-order-track-id');
$orders = Order::where('code', $orderCode)->get();
if($orders->isEmpty()){
return redirect('/track')->with('error', 'Order not found.');
}else{
$order = Order::where('code', $orderCode)->first();
return redirect('/track/' . $order->code);
}
}

Redirect back with input not working in laravel 5.5

I've used redirect back with input many times previously. But in this project I'm unable to do so. This is my controller method that handles the form request:
public function verifyMobileCode( Request $request)
{
$userId = Auth::user()->id;
if( Auth::user()->verification_code == $request['verification_code'])
{
User::where('id', $userId)->update(['verified'=>1]);
return redirect('/')->with('success', 'Account verified.');
}
else
{
return redirect()->back()->withErrors('verification_code' ,'unv' )->withInput($request->all());
}
}
This is my form blade:
#extends('layouts.index')
#section('content')
<div class="container" style='padding-top: 150px;'>
<?php var_dump($errors) ; ?>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Verify your mobile</div>
<div class="panel-body">
<form class="form-horizontal" method="POST" action="{{ route('verifyMobileCode') }}">
{{ csrf_field() }}
<div class="form-group{{ $errors->has('verification_code') ? ' has-error' : '' }}">
<label for="verification_code" class="col-md-4 control-label">Verification code</label>
<div class="col-md-6">
<input id="verification_code" type="text" class="form-control" name="verification_code" value="{!! old('verification_code') !!}" required autofocus maxlength="6" pattern="\d{6}">
#if ($errors->has('verification_code'))
<span class="help-block">
<strong>Please enter 6 digit number sent to your mobile.</strong>
</span>
#endif
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<button type="submit" class="btn btn-primary">
Register
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
#endsection
My Kernel.php is as follows:
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* 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,
\App\Http\Middleware\LanguageSwitcher::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
];
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* #var array
*/
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'is-admin' => \App\Http\Middleware\IsAdminMiddleware::class,
];
}
I do not find any error or something wrong. Is there anything you see? Is there any technique to debug this behaviour? Thaks in advance.
My approach would be using FormRequest.
php artisan make:request VerifyCodeRequest
And body of the request:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class VerifyCodeRequest 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 [
'verification_code' => 'required|in:'.$this->user()->verification_code, // since user is already logged in we check if verification_code matches using `in` rule
];
}
public function messages()
{
return [
'in' => 'Your custom error message if we failed',
];
}
}
Now you change signature of verifyMobileCode(...) to the following verifyMobileCode(App\Http\Requests\VerifyCodeRequest $request).
Now, code executes body of the function only if we pass the validation so we need to update user instance and we are done.
public function verifyMobileCode(App\Http\Requests\VerifyCodeRequest $request)
{
$request->user()->verify();
return redirect('/')->with('success', 'Account verified.');
}
Inside User model add verify() function
public function verify()
{
$this->update(['verified' => true]);
}
If your above approach does not work the there is some issue with your app/Http/Kernel.php. You have used
\Illuminate\Session\Middleware\StartSession::class,
twice. You must delete one. Probably the first one.
See the stock Laravel's kernel.php.
Replace ->withInput($request->all()); with ->withInput();
if you dont want any one of the input use
->withInput(
$request->except('input_name')
);
To debug this without resorting to Xdebug the quick way is to add temporary debug code to the start of the blade file:
#php
dd($errors->toArray(), $errors->has('verification_code'));
#endphp
Which will give you the following output:
array:1 [
0 => array:1 [
0 => "verification_code"
]
]
false
This shows that the logic in the blade file is not being evaluated to true which is required to show the error styles and message.
The quick fix is to change the controller to use:
->withErrors(['verification_code' => 'unv'])
withErrors expects as MessageBag or array, but will cast a string to an array which does not result in the proper key/value pair.
The debug output will now show:
array:1 [
"verification_code" => array:1 [
0 => "unv"
]
]
true
The debug code can now be removed and the error should be displayed as you expect.
The proper Laravel way is probably to use $request->validate() or a FormRequest for complex forms. For more information see the Laravel validation documentation (https://laravel.com/docs/5.5/validation).
Your Controller should look like this:
public function verifyMobileCode( Request $request)
{
$userId = Auth::user()->id;
if( Auth::user()->verification_code == $request['verification_code'])
{
User::where('id', $userId)->update(['verified'=>1]);
return redirect('/')->with('success', 'Account verified.');
}
else
{
return redirect()->back()->withErrors('message' ,'Please some errors encountered.' );
}
}
And modify this
<div class="form-group{{ $errors->has('verification_code') ? ' has-error' : '' }}">
To this:
<div class="form-group>
#include('errors');
Also create file called errors.blade.php in resources/views and put the following code:
#if ($errors->any())
<div class="card"> //incase bootstrap 4
<div class="error card-body alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
</div>
#endif
Hope it works for you. But you dont need to display old inputs since the code will be wrong or something wrong has happened. So its not necessary
return redirect()->back()->withInput()->withErrors('verification_code' ,'unv' );
In controller
return redirect()->back()->withErrors('verification_code' ,'unv')->withInput();
In view
if you want to retrieve the validated input field value then you need to use laravel FORM class for <form></form> as well as <input> fields
example
{{ Form::open(['method' => 'post','url' => 'Your url','class'=>'form-horizontal']) }}
{{ Form::text('verification_code','',['class'=>'form-control']) }}
{{ Form::close() }}
anybody on Laravel 8, this should work
return back()->withErrors('your error message is here');
If you look at the signature of the withErrors function, second param is the key and it is set to default unless you want it to be something specific.

Laravel error "Missing required parameters for Route" when I use a form with a foreach loop

Missing required parameters for [Route: templates.answers.store] [URI: templates/{template}/answers]. (View: D:\Applications\xampp\htdocs\clientpad\resources\views\templates\answers.blade.php)
I am having the above error when I try and use a form with my foreach loop. I am not even sure why this is happening, maybe because I am new at Laravel. But this error goes away once I get rid of the AnswerController#store from the Eloquent form. It is possible I am doing this whole form wrong.
Here is what I want to do: A user made a template with questions, on the click of use button which goes to this url: http://clientpad.test/templates/{id}/answers they see their made questions which are shown with a foreach loop. Around it a Form is made so a user can answer the questions made. The form and answer field shows when I delete the action AnswerController#store, otherwise I get the above error.
Here is the code:
AnswerController:
public function index(Template $template, Question $question)
{
$questions = $template->questions->mapWithKeys(function($question){
return [$question->id => $question->question];
});
return view('templates.answers')->with('template', $template)->with('questions',$questions);
}
public function store(Request $request, Question $question, Answer $answer)
{
$answers = new Answer;
$answers->answer = $request->input('answer');
$answers->question_id = $request->input('question_id'); //current template id
$question->answers()->save($answers);
dd($question);
return redirect('/dashboard')->with('success', 'Your Question Was Successfully Created');
}
answers.blade.php
{!! Form::open(['action' => 'AnswersController#store', 'method' => 'POST']) !!}
#foreach ($questions as $question) <!-- Index counts the questions shown -->
<div class="panel panel-default">
<div class="panel-body">
<p class="pull-left question2"> {{$question}}</p>
<div class="form-group answer">
{{Form::label('', '')}}
{{Form::text('answer', '', ['class' => 'form-control', 'placeholder' => 'Type in your answer'])}}
</div>
</div>
</div>
#endforeach
<hr>
{{Form::submit('Save', ['class'=>'btn btn-primary'])}}
{!! Form::close() !!}
And I am just using the resource in routes.
Your are calling a route templates/{id}/answers in your Blade view that is missing the {id} parameter. Reading the error thoroughly will help you understand.
Instead of writing:
Form::open(['action' => 'AnswersController#store', 'method' => 'POST'])
You write:
Form::open(['action' => ['AnswersController#store', $template_id], 'method' => 'POST'])
The $template_id will fill the {id} in your route URL templates/{id}/answers.

Allow saving an existing entry in Laravel with FormRequest and unique

Still noob and learning Laravel, I am currently in the middle of a simple validation with FormRequest. What I am facing today is the edit of an existing entry.
I have written in my FormRequest that I want the name to be unique. It works perfectly but of course when I edit an existing entry, I cannot save it anymore, it already exists... of course it does since I am editing it.
I found the solution reading the documentation, but unfortunately, it does not work. Here's my code:
Routes:
Route::resource('editeurs', 'PublishersController');
Controller:
class PublishersController extends Controller
{
/* Update an existing publisher */
public function update($slug, PublisherRequest $request)
{
$publisher = Publisher::where('slug', $slug)->firstOrFail();
$input = $request->all();
$publisher->name = $input['name'];
$publisher->slug = my_slug($input['name']);
$publisher->save();
return redirect()->action('PublishersController#show', $publisher->slug);
}
}
FormRequest:
class PublisherRequest extends Request
{
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required|unique:publishers,name,'.?????
];
}
}
If needed, the view:
#section('content')
<div class="row">
<h1 class="large-12 columns">Edition - {!! $publisher->name !!}</h1>
{!! Form::model($publisher, ['method' => 'PATCH', 'action' => ['PublishersController#update', $publisher->slug]]) !!}
<div class="large-12 columns">
{!! Form::label('name', 'Nom de l\'éditeur') !!}
{!! Form::text('name', null, ['placeholder' => 'Nom de l\'éditeur']) !!}
</div>
<div class="large-12 columns">
{!! Form::submit('Ajouter un éditeur', ['class' => 'button expand']) !!}
</div>
{!! Form::close() !!}
</div>
#stop
What is wrong with my code?
Here is how I would do it:
class PublishersController extends Controller
{
/* Update an existing publisher */
public function update($slug, PublisherRequest $request)
{
$publisher = Publisher::where('slug', $slug)->firstOrFail();
$this->validate($request, ['name' =>'required|unique:publishers,name,'.$publisher->id]);
$publisher->name = $request->input('name');
$publisher->slug = my_slug($publisher->name);
$publisher->save();
return redirect()->action('PublishersController#show', $publisher->slug);
}
}
OK, I found the solution. I needed to pass the slug of my current publisher.
public function rules()
{
$publisher = Publisher::where('slug', $this->editeurs)->first();
return [
'name' => 'required|unique:publishers,name,'.$publisher->id
];
}
This works.

Resources