POST method not supported for route in Laravel 6 - laravel

I am building a discussion form in Laravel 6. The route I used is a POST method and I checked it in route:list. I get the following error, why?
The POST method is not supported for this route. Supported methods:
GET, HEAD, PUT, PATCH, DELETE
View
<form action="{{ route('replies.store', $discussion->slug) }}" method="post">
#csrf
<input type="hidden" name="contents" id="contents">
<trix-editor input="contents"></trix-editor>
<button type="submit" class="btn btn-success btn-sm my-2">
Add Reply
</button>
</form>
Route
Route::resource('discussions/{discussion}/replies', 'RepliesController');
Controller
public function store(CreateReplyRequest $request, Discussion $discussion)
{
auth()->user()->replies()->create([
'contents' => $request->contents,
'discussion_id' => $discussion->id
]);
session()->flash('success', 'Reply Added.');
return redirect()->back();
}

You passed a disccussion object as parameter in order to store user_id within an array.
I think this is not a good practice to store data.
You might notice that your routes/web.php and your html action are fine and use post but you received:
"POST method not supported for route in Laravel 6". This is runtime error. This probably happens when your logic does not make sense for the compiler.
The steps below might help you to accomplish what you want:
1. Eloquent Model(App\Discussion)
protected $fillable = ['contents'];
public function user(){
return $this->belongsTo('App\User');
}
2. Eloquent Model(App\User)
public function discussions(){
return $this->hasMany('App\Discussion');
}
3. Controller
use App\Discussion;
public function store(Request $request){
//validate data
$this->validate($request, [
'contents' => 'required'
]);
//get mass assignable data from the request
$discussion = $request->all();
//store discussion data using discussion object.
Discussion::create($discussion);
session()->flash('success', 'Reply Added.');
return redirect()->back();
}
4. Route(routes/web.php)
Route::post('/replies/store', 'RepliesController#store')->name('replies.store');
5. View
<form action="{{ route('replies.store') }}" method="post">
#csrf
<input type="hidden" name="contents" id="contents">
<trix-editor input="contents"></trix-editor>
<button type="submit" class="btn btn-success btn-sm my-2">
Add Reply
</button>
</form>

Related

Laravel 9 how to pass parameter in url from one controller to another controller?

I was facing this problem of missing parameter when trying to pass a parameter from one controller to another controller. The parameter is $id whereby the data is originally from post method in details blade.php into function postCreateStepOne However, I want to pass the data into a new view and I return
redirect()->route('details.tenant.step.two')->with( ['id' => $id]
);}
And this is where error occur. However, it works fine if I skip it into a new route and directly return into a view with the compact parameter. For Example,
return view('document.details-step-two', compact('id', 'property'));
However, I would prefer a new url as I was doing multistep form using Laravel.
Error
web.php
Route::get('/document/details/viewing/{id}', 'ViewDetails')->name('details.tenant');
Route::post('/document/details/viewing/{id}', 'postCreateStepOne')->name('post.step-one');
Route::get('/document/details/viewing/step-2/{id}', 'ViewDetailsStep2')->name('details.tenant.step.two');
TenanatController.php
public function viewDetails($id){
$view = Properties::findOrFail($id);
return view('document.details', compact('view'));
}
public function ViewDetailsStep2(Request $request, $id){
$view = Properties::findOrFail($id);
$property = $request->session()->get('property');
return view('document.details-step-two', compact('view', 'property'));
}
public function postCreateStepOne($id, Request $request)
{
$validatedData = $request->validate([
'property-name' => 'required',
]);
if(empty($request->session()->get('property'))){
$property = new Tenancy();
$property->fill($validatedData);
$request->session()->put('property', $property);
}else{
$property = $request->session()->get('property');
$property->fill($validatedData);
$request->session()->put('property', $property);
}
return redirect()->route('details.tenant.step.two')->with( ['id' => $id] );
}
details.blade.php
<form action="{{ route('post.step-one', $view->id) }}" method="POST">
#csrf
<div class="card-body">
<div class="form-group">
<label for="title">Property Name:</label>
<input type="text" value="" class="form-control" id="property-name" name="property-name">
</div>
</div>
<div class="card-footer text-right">
<button type="submit" class="btn btn-primary">Next</button>
</div>
</form>
When you use with on a redirect the parameter is passed through the session. If you want to redirect to a route with a given route parameter you should pass that parameter in the route function itself like e.g.
return redirect()->route('details.tenant.step.two', ['id' => $id]);

404 not found on laravel post request

I'm making a post request in my form. The csrf token and the method are there.
<div class="flex">
<form action="{{ route('profile.store.follower', $user) }}" method="post">
#csrf
<input value="follow" type="hidden" name="follow" value="{{$user->id}}" >
<button type="submit" class="bg-green-700">Follow</button>
</form>
</div>
The route:
Route::get('/usersprofile/{user:name}/index', [ProfileController::class, 'index'])->name('profile.index');
Route::post('/usersprofile/{user:name}/index', [ProfileController::class, 'store'])->name('profile.store.follower');
The controller:
public function store(User $user, Request $request) {
dd($user);
$user = user::findOrFail($request->follow);
Auth::user()->following->attach($user->id);
return back();
}
The following function in the user model:
public function following() {
return $this->belongsToMany(User::class, 'followers', 'user_id', 'following_id');
}
For some reason, it's not going through. I've tried php artisan route:cache and config:cache but the error persists. I've checked the route list and the route exists.
Your hidden input has two value attributes, that's probably why it doesn't find a user and fails.
Remove the hidden input and the line $user = user::findOrFail($request->follow); - the user you want to follow already exists in $user via your route. Then use Auth::user()->following->attach($user); to follow.
<div class="flex">
<form action="{{ route('profile.store.follower', $user) }}" method="post">
#csrf
<button type="submit" class="bg-green-700">Follow</button>
</form>
</div>
public function store(User $user, Request $request)
{
Auth::user()->following->attach($user);
return back();
}

Multiple files upload Laravel 5.8

I want to upload multiple files in Laravel but it's not working I tried in my controller
Edit: I means page refresh but no error or registred data in the db
I followed https://www.youtube.com/watch?v=wk5usyevYj0
public function storescan(Request $request){
$this->validate($request,[
'file' => 'required|file|mimes:gif,jpg,png,jpge,jpeg|max:102048'
]);
$files=$request->file('file');
foreach($files as $file){
Document::create([
'doc'=>$file->getClientOriginalName(),
'path'=>$file->store('public/storage'),
'support'=>$request->input('support'),
'ecole'=>$request->input('ecole'),
'jour'=>$request->input('jour'),
'cycle'=>$request->input('cycle'),
'type'=>'Image',
'niveau'=>$request->input('niveau'),
'matiere'=>$request->input('matiere'),
'user_id'=>Auth::user()->id
]);
}
return redirect()->route('prof.document.create')->withMessage('✅ Image(s) ajoutée(s) avec succès!');
}
And here is my route and formular
Route::post('/professeur/myDoccy/scan/create','DocumentController#storescan')->name('prof.document.createscan');
Formular everything is correct I minimized the code and left only the input file
<form enctype="multipart/form-data" class="form" action="{{ route('prof.document.createscan') }}" method="POST">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
{{ csrf_field() }}
<label class="purple" >Charger l’image </label><br/>
<input required type="file" multiple name="file[]" accept='image/*' class="form-control-file border-or m-1" >
</div>
</form>
You should check $errors variable (read more https://laravel.com/docs/5.8/validation).
You have problem with validation. You have rule
'file' => 'required|file|mimes:gif,jpg,png,jpge,jpeg|max:102048'
But it will work for single file. You have multiple of them, so it should be:
'file.*' => 'required|file|mimes:gif,jpg,png,jpge,jpeg|max:102048'
Also, you can use "image" rule instead of file with all mimes.
I solved the issue by deleting the validate part
And adding to all fillable attributes in my model but still no validation possibility
class Document extends Model
{
use SoftDeletes;
public function user(){
return $this->belongsTo('App\User');
}
protected $fillable = [
'doc','support','ecole',
'path',
'jour',
'cycle',
'type',
'niveau',
'matiere',
'user_id'
];
}
function
public function storescan(Request $request){
$files=$request->file('file');
foreach($files as $file){
Document::create([
'doc'=>$file->getClientOriginalName(),
'path'=>$file->store('public/storage'),
'support'=>$request->input('support'),
'ecole'=>$request->input('ecole'),
'jour'=>$request->input('jour'),
'cycle'=>$request->input('cycle'),
'type'=>'Image',
'niveau'=>$request->input('niveau'),
'matiere'=>$request->input('matiere'),
'user_id'=>Auth::user()->id
]);
}
return redirect()->route('prof.document.create')->withMessage('✅ Image(s) ajoutée(s) avec succès!');
}

Targeting one row, not all that has a certain value

I have a basic adding system, that allows landlords to add tenants, and tenants then have the ability to accept/reject. Accepting is very simple, when the tenant clicks accept, the accept boolean changes to 1. At the moment this is changeing all rows to accepted, not just the one between the landlord and tenant.
This is an example row in the database:
If a tenant clicks accept, the accepted row will change to 1, and request sent will revert to 0. The users are now connected.
However, all rows that have accepted = 0, and request = 1, will be affected, not just the current row.
This is the accepted controller
public function accept(Request $request)
{
Tenancy::where('accepted', 0)
->where('request_sent', 1)
->where('tenant_id', Auth::id())
->update([
'accepted' => 1,
'request_sent' => 0,
]);
return back();
}
Any ideas?
EDIT
Route URL
Route::post('/account/tenancy/{id}/accept', 'AccountController#accept')->middleware('auth');
Entire form and logic for accept/reject
#if($currentUser->userType == "Tenant")
#if($tenancy == null ||$tenancy->accepted == 0 && $tenancy->request_sent == 1 && $tenancy->tenant_id == $currentUser->id)
<form method="POST" action="/account/tenancy/{{$user->id}}/accept">
{{ csrf_field() }}
<input type="submit" class="btn btn-primary" value="Accept Request">
</form>
<form method="POST" action="/account/tenancy/{{$user->id}}/reject">
{{ csrf_field() }}
<input type="submit" class="btn btn-warning" value="Reject Request">
</form>
#endif
dd($tenancy)
Based on your comments/recent edits, i believe this should work:
Change all
action="/account/tenancy/{{$user->id}}/accept"
to
action="/account/tenancy/{{$tenancy->id}}/accept"
and your accept/reject methods in the controller like this:
public function accept(Request $request, string $id)
{
Tenancy::find($id)
->update([
'accepted' => 1,
'request_sent' => 0,
]);
return back();
}
You are missing another where. You are just filtering for the two statuses and the tenant_id, but you want to filter by the landlord_id aswell.
Something like Tenancy::where('accepted', 0)->where('request_sent', 1)->where('tenant_id', Auth::id())->where('landlord_id', $id);.
However, what happens, if there are two tenancies between a landlord and a tenant? You probably want to pass the tenancy id in the request and retrieve the tenancy in your accept function by the id. Important thing to keep in mind here is to make sure, that the current user is allowed to accept the tenancy with the id he passed.
Edit based on your new code in the question:
This would be the approach of my recommendation, not the additional landlord_id.
<form method="POST" action="/account/tenancy/{{$tenancy->id}}/accept">
{{ csrf_field() }}
<input type="submit" class="btn btn-primary" value="Accept Request">
</form>
public function accept(Request $request, $id)
{
Tenancy::find($id)
->update([
'accepted' => 1,
'request_sent' => 0,
]);
return back();
}
You should still keep in mind, that an authorization/check would be needed.

Delete A Record From A Relationship

I want to delete a record: remove a routine,that belongs to a user, on button click (hasMany). I have set up the view, models and relationship within,delete route, and the controller method to delete.
When I try to click the button to remove the routine from the db, it does nothing. why does it not removing the record?
Here's my code: route:
Route::post('routine/delete', 'RoutineController#delete'); // Delete a routine for a user.
Controller:
public function delete(Request $request)
{
$id = $request->input("id"); // Getting the id via. the ajax request.
$routine = \App\Routine::find($id); //Fetching the routine object from the db ifentified by the id passed via ajax
if ($routine)
{
$routine->delete();
}
return ["status" => "success"];
}
View:
<div class="col-lg-2">
<!-- When this button is clicked, we determine which routine to remove. -->
<button class="btn btn-danger remove_routine" data-id="{{$routine->id}}" data-token="{{csrf_token()}}" style="display:inline">Delete</button>
</div>
User Model:
public function routine()
{
return $this->hasMany('App\Routine');
}
Routine model:
public function user()
{
return $this->belongsTo('App\User');
}
Thanks in advance!
Don't know if it exactly answers your question, and I don't use AJAX, but I always do my deletes like this:
View
#foreach($database-thing as $item)
<form method="POST" action="$yourActionHere" style="display:inline" >
<input name="_method" type="hidden" value="DELETE">
<button type="submit" class="btn btn-danger btn-xs"><i class="fa fa-trash"></i> Delete</button>
</form>
#endforeach
// Even easier with laravelcollective/forms
#foreach($database-thing as $item)
{!! Form::open([
'method'=>'DELETE',
'url' => [$yourUrl, $item->id // <-- Very important],
'style' => 'display:inline'
]) !!}
{!! Form::button('<i class="fa fa-trash"></i> Verwijder', ['type' => 'submit', 'class' => 'btn btn-danger btn-xs']) !!}
{!! Form::close() !!}
#endforeach
Controller
public function destroy($id)
{
YourModel::destroy($id);
// All your other logic like redirects and stuff
}
Working delete, based on the code above and this updated controller function:
public function delete(Request $request,$id)
{
$user=Auth::user();
$routine = \App\Routine::findOrFail($id); // find or throw an error if you don't find the routine id in db.
// Makes if() statement redundant, since it checkes for that id already.
// Need to check that the owner of the routine is the current authenticated user.
if ($user->id != $routine->user->id)
{
Session::flash('flash_message', 'No routine found.');
}
else
{
$routine->delete();
Session::flash('routine_deleted','Routine deleted!');
}
// No need to return $routine since I am deleting it, otherwise it will throw and error of trying to get property of non-object.
return redirect()->back()->with('user') ;
//return view('view_routine')->with('user', 'routine');
}
There you go
$remove = 2;
$filtered = $c->filter(function ($value, $key) use($remove){
return $value['id']!=$remove;
});

Resources