Laravel create controller method to update 1 column from 1 row - php

I am making a website for a dog shelter, and I want to make a button which would mark the dog as adopted. In other words, I am trying to update 1 column from 1 row. It will always be set from false to true.
I have tried making my own method in my existing controller, adding a route and creating a form, but I get errors that some other fields are also required, which are the same required fields when I would create a new dog (name, sex, DoB etc).
Code of the method in my controller:
public function markAsAdopted(Request $request, $id){
$pet = Pet::table('pets')->where('id', $id)->update(['is_adopted' => true]);
return redirect("/pets/$pet->id")->with('success', 'Successfully marked as adopted');
}
Code of the route:
Route::patch('/pets/{id}', 'PetsController#markAsAdopted');
Code of the form:
{!! Form::open(['action' => ['PetsController#markAsAdopted', $pet->id], 'method' => 'POST', 'class' => 'float-right ml-1 mr-1']) !!}
{{Form::hidden('_method', 'PATCH')}}
{{Form::submit('Mark as adopted', ['class' => 'btn btn-success'])}}
{!! Form::close() !!}
The form is on the page /pets/{id}
I have created all the other routes in this controller with the --resource flag when creating the controller, so the skeleton of CRUD was there.
Did I miss something? OR is there a better way of doing this?

Laravel is routing the markAsAdopted call to your update() (or possibly create() depending on how you have your Routes set) instead of the markAsAdopted() method. This is, in turn, calling your PetsRequest class (or whatever you've called your verification class).
It is most likely coming in as a POST and possibly ignoring the PATCH method, thus routed to update(). You can do a couple of things - move the patch method higher in Routes file and test by changing to POST. If this works, you know this is the problem. This is just a test - you will break the other pets POST coming in below it in the Routes file, so remember to change it back :)
I typically skip the PATCH thing altogether though, as I've run into similar issues. I normally just make a POST route with a special name (e.g. Route::post('/petsMarkAsAdopted/{id}', 'PetsController#markAsAdopted');) and open the form with the url to that special route.
If you really want to keep the PATCH, do the higher placement test above, and you can use blade to set the method after you open your form, like so:
#method('PATCH')
Edit: As noted in the comments, the above fixes the routing, but there is a different problem in your controller method now that we can access it. Take out the table(), and just call the model to get the pet your need. I've separated out the call for clarity:
$pet = Pet::where('id', $id)->first();
$pet->update(['is_adopted' => true]);

Related

MethodNotAllowedException when send post form with csrf_token Laravel 5.4

I'm trying to access my "store" (POST) method from my route resource. I call the ProductCRUD.store method from a form that can have different input depending on the previous page. I mean by that, depending if the object i receive have certain boolean value, the input is shown.
#if($category->havePrice == 1)
{!! Form::label('price', 'Price') !!}
{!! Form::text('price', '', array('id' => 'price', 'name' => "price") !!}
#endif
When I click on the button to send the form, I got a message saying
MethodNotAllowedHttpException in RouteCollection.php line 251:...
I tried to add a csrf token with the method csrf_field() too.
I tried to empty the cache of laravel with those two methods:
php artisan cache:clear
php artisan route:cache
I tried to create a personal route like this:
Route::post('/product/store', array('as' => 'product', 'uses' => 'ProductController#store'));
None of those solution works. Always that exception.
My current code:
Route:
Route::resource('ProductCRUD','ProductController');
Form
<form method="POST" action="{{route('ProductCRUD.store')}}">
{{ csrf_field() }}
Controller method:
public function store(Request $request) {
$newGameModel= new GameModel();
$category = $this->CategoryRepo->getByID($request->category);
$this->validate($request, [
'name'=> 'required',
'picture'=> 'required|image|mimes:jpg,jpeg,gif,png|max:5000',
'quantite' => 'required|min:0',
'price' => 'required_if:'.$category->havePrice.',1',
]);
...
}
If I remove the "$this->validate(...)" method the code continues to execute (no more MethodNotAllowedException error). I tried to comment one by one validation it changes nothing.
Plus, if I reload the page, the input error are shown correctly. If i click again to send the form, surprise! The error again.
Edit:
I send my form using only a button and the form, no ajax:
{!! Form::submit('Next step', 'name'=>"accept", 'methode' => "post")) !!}
Plus, I can access my controller code. If I remove the validate method, everything work find
Do you guys have any idea why it's doing that? Thank you for your time!
Ok, so I found the problem and how to fix it (not what I wanted to do).
First, I don't have any error in my code. My post, csrf and my routes are all good.
The problem is how larval validates things. For example, If your first page was a post form and your second page is also a post form, when you validate on the second page and it fails, it will try to return to the second page to show the error. But the fact is, it can't find the response of your first page, so you got an error like I got.
I fix it by removing the first form (it was, for me, a little information I can put somewhere else). But I don't know if there is a better way to fix it.

Laravel Gates and Policies

The following Gate definitions are working fine:
Gate::define('create_role','App\Policies\RolePolicy#create_role');
Gate::define('view_role','App\Policies\RolePolicy#view_role');
Gate::define('edit_role','App\Policies\RolePolicy#edit_role');
Gate::define('delete_role','App\Policies\RolePolicy#delete_role');
but when I changed it to,
Gate::resource('roles', 'App\Policies\RolePolicy', [
'create_role' => 'create_role',
'view_role' => 'view_role',
'edit_role' => 'edit_role',
'delete_role' => 'delete_role',
]);
for reducing LOC and optimizing code. It is not working.
Following are the lines of code in my blade file,
#can('create_role')
Add Role
#endcan
#can('view_role')
View Roles
#endcan
Similarly for edit and delete.
The behavior observed is as such that it is only receiving false from the policy methods. I even tried out sending only true from it, but makes no difference.
Are you trying to create extra gates?. Given you passed that extra parameter in the array.
The array after gate definition is used to create extra gate definitions.
For more info go through the docs,
link.
When using resourceful policies.
eg:
Gate::resource('roles', 'App\Policies\RolePolicy');
#can('roles.view')
// html here
#endcan
#can('roles.create')
//html here
#endcan

Extra strange segment in a form action URL automatically added by laravel

I have this form:
{!!Form::open(['route'=>'fastsearch.show'])!!}
In routes.php I have:
Route::resource('fastsearch','SearchController');
And in SearchController i have a method show() that sends the return to a view called fastsearch (which is fastsearch.blade.php)
If I look into the source of the page where the form is, I see this:
<form method="POST" action="http://localhost:8000/fastsearch/%7Bfastsearch%7D" accept-charset="UTF-8"><input name="_token" type="hidden" value="hLcSkGk2p5XfTkFEv2pwGgcVQB18vHQIGMpOVGpM">
If I put some data in the form and click Submit, I get this error:
MethodNotAllowedHttpException in RouteCollection.php line 201:
My question is why the extra segment in the action URL (this one: /%7Bfastsearch%7D). Is something wrong with the routes ?
(Just to give you all the details, this a general search form that lies on almost every page in order to allow the users to run a quick search from almost every page they might be at that time. So it doesn’t matter if you’re on Home page or on /Home/Subpage/SubSubPage{wildcard}{wildcard} you can still see the form and use it)
You're trying to send a post request to a route expecting a get request.
Change:
{!! Form::open(['route'=>'fastsearch.show']) !!}
To:
{!! Form::open(['route'=>'fastsearch.index']) !!}
Where index is the name of the action you wish to receive the post request.
You're probably better off using specific named routes for this though.
Route::post('fastsearch', [
'as' => 'fastsearch.search', 'uses' => 'SearchController#search'
]);
Take a look at http://laravel.com/docs/5.1/controllers#restful-resource-controllers for more info on resource controllers and http://laravel.com/docs/5.1/routing#named-routes for more on named routes.
You can also use ./artisan route:list for a list of existing routes.

Laravel 5 Form parameter issue

Ok so I have added in the Form functionality just fine in Laravel 5 and have been using it through out these tutorials. I am brand new to Laravel in general and can't see to find out what is going wrong. I have a nested route that is todos.items.create, so to create a new item in that list I would have to pass that ID into the Form::open tag. However when doing so I get a Whoops, looks like something went wrong. Now if I remove the $todo_list->id parameter the page loads fine but with it I always get this error. Here is my code
Controller:
public function create($list_id)
{
$todo_list = TodoList::findOrFail($list_id);
return view('items.create', ['TodoList' => $todo_list]);
}
Create View (create.blade.php in side my items folder inside the views folder)
{!! Form::open(array('route' => ['todos.items.store', $todo_list] )) !!}
When just doing the below it renders fine but doing the above which is needed it doesn't. This is because I need the id of the list in which to create the new item in.
{!! Form::open(array('route' => ['todos.items.store'] )) !!}
Routes:
Route::get('/', 'TodoListController#index');
Route::resource('todos', 'TodoListController');
Route::resource('todos.items', 'TodoItemController', ['except' => ['index', 'show'] ]);
Any ideas what I am doing wrong here? I have ran a var_dump of $todo_list->id before the return of the view just to check things and it returned the proper id.
You've created the $todo_list object but have passed it to your view as $TodoList.
Try using the following instead
return view('items.create', ['todo_list' => $todo_list]);
When calling the view from the controller, the key used in your array of data is what the variable will be available as on the pages.

Laravel NotFoundHttpException on route

I have been struggling with something very simple here nevertheless the vagueness around Laravel's routing system that complicates its easy routing approach. I have gone through questions listed here but nothing seems to help me so here it goes.
I have formerly defined a route to my controller on an action named "create". This action is suppose to accept a post data from the form and persist it. This create method has one parameter which defaults to null for a project id if its add else we pass an id e.g domain/projects/add/22 to edit and domain/projects/add to create a new one.
Below is the skeleton of the function:
public function create( $id = null ){ ... }
I then defined a route for this which is:
Route::post( 'projects/add', 'ProjectsController#create' );
Inside my form I have {{ Form::open(array('url' => 'projects/add', 'method' => 'post')) }} .
I keep on getting errors related to routing, Http or method not found exceptions. I tried to follow every suggestion on the net but cannot for the life of me find my way.
Please help me point to the right direction, thanks.
try with below sample code
routs.php►
Route::post('projects/add/{id?}',array('as'=>'project_create','uses'=>'ProjectsController#create'));
ProjectsController.php►
class ProjectsController extends BaseController{
public function create( $id = null ){
...
}
projects.blade.php► (for used blade templating your views should have blade.php extention )
<html>....
<form action="{{ route('project_create') }}"method="post">
....
</form>
</html>
Thank you guys for all your responses. After being swamped with work I finally came back to my project and wanted to try out some of your suggestions but I failed.
I did find a tutorial that I tried to follow and basically was able to have my routes working.
Inside the routes I added (see below):
Route::get('/projects/list', [
'as' => 'post.list',
'uses' => 'ProjectsController#listProjects'
]);
Inside my controller I just created a function that is named listProjects(). As for getting my form displayed I followed the same pattern except point to newProject() method in my controller.
As much as I was not keen on this approach I ended up creating another function just for saving my POSTed form data after a new project form has been filled out and submitted. I still used the same url as projects/add except pointing it to a different function in may controller named saveProject().
About the view I just added the as part of the same save route and it worked. below is a link to the tutorial I followed and taking a look at the code.
http://www.codeheaps.com/php-programming/creating-blog-using-laravel-4-part-1/

Categories