Laravel form best practice ? Hidden input OR Route parameter? - php

I am wondering what is the best practive between sending data through route parameters or hidden inputs in Laravel, or in general. For example, what is the best way in your opinion between :
Route path parameters
/*** Html form --> User and Account ID are sent as route parameters ***/
<form method="post" action="/associate/user/10/account/34">
{{ csrf_field() }}
<input type="submit" />
</form>
/*** Route ***/
Route::post('/associate/user/{user_id}/account/{account_id}', 'UserController#associate');
/*** Controller ***/
public function associate($user_id, $account_id) {
$user = App\User::find($user_id);
$account = App\Account::find($account_id);
$user->account()->associate($account);
$user->save();
return back();
}
OR
Form hidden inputs
/*** Html form --> User and Account ID are sent as hidden inputs ***/
<form method="post" action="/associate/user-account">
{{ csrf_field() }}
<input type="hidden" name="user_id" value="10" />
<input type="hidden" name="account_id" value="34" />
<input type="submit" />
</form>
/*** Route ***/
Route::post('/associate/user-account', 'UserController#associate');
/*** Controller ***/
public function associate(Request $request) {
$user = App\User::find($request->input('user_id'));
$account = App\Account::find($request->input('account_id'));
$user->account()->associate($account);
$user->save();
return back();
}
What do you think ?
Thanks a lot for your opinion.

My opinion on this is to use Route parameters where it makes sense.
It is not very clear in your example on what you're trying to achieve, i.e. having two pre-defined values as hidden inputs and just a submit button doesn't seem like a very practical real-world scenario.
Say, if you have a form to associate given user to an account, what you might be able to do is have the user_id as part of route parameters, and the account_id as a dropdown. This way your form might look something like this:
{{-- /user/{user_id}/associate-account --}}
<form action="{{ route('user.associate-account', [
'user_id' => $userId
]) }}>
{{ csrf_field() }}
<select name="account_id">...</select>
</form>
Your controller
public function associate(Request $request, $userId)
{
}
The advantages of this:
1. You can consistently group routes, related to user object.
Example:
Route::group(['prefix' => 'user/{user_id}'], function ()
{
Route::post('/associate-account', 'UserController#associate');
Route::post('/upgrade-account', 'UserController#upgradeAccount');
Route::post('/delete', 'UserController#delete');
});
As you can see it's very clear from the route that those three POST actions are all tied to given user_id
2. You can utilise Model Binding
Model Binding essentially turn your Model key, into actual Model instance, such that you can write your controller action as:
public function associate(Request $request, User $user)
{
// Here `user_id` has been converted into actual User model instance
// by default Laravel also throws ModelNotFoundException when User
// can't be found with given `user_id`
$user->account()->associate($request->get('account_id'));
}
As of Laravel 5.2 you can implicitly bind model to your route, prior to this you have to register them first.

This isn't so much a question about Laravel as it is about routing. It’s really about how you want to design your app’s routes, and what is logical to you, and those others who may work with it.
If you’re going for a more RESTful approach, the former would be better (and what I tend to prefer). It makes your routes appear logically organized, which is better suited for making api’s that others will potentially use.
Otherwise, if you don’t intend to scale your app that far, and don’t care to have an api with smexy url’s, just go with the latter approach. I only recommend you be consistent with the one you pick.
Unless I missed something (which is possible), it just looks like two ways to skin a cat.

Related

Laravel match and any method

I´m working with Laravel building a web app. This app will contain a FORM that only asks a name of a requisite of a client that will be added in to a database. I´m trying to obtain the ID of the client by 'GET' method and the title of the requisite by 'POST' method. I´ve tryied to use 'MATCH' metchod but that brings me errors.
These is the code in the view:
<form action="{{ route('folders.store') }}" method="post">
#csrf
#method('match')
...
</form>
These in the web:
Route::match(['get', 'post'], 'folders/store', [PartnerController::class, 'store'])-> name('folders.store');
and these in the controller:
public function store(Request $request)
{
#dump($request);
return $request;
}
In the last I´m just trying to verify want I´m doing. jaja.
Thank you.
I´ve tryied using method 'any', with no results.
I´ve changed the 'post' to 'get' method but it´s not a really secure option.
I think I don´t really understand what I´m doing at all.
you're out of conventions but anyway if you're user logs in you can get the id with Auth::id(), but if not, go with this
Route::post('folders/store/{$id}', [PartnerController::class, 'store'])-> name('folders.store');
then in form
<form action="{{ route('folders.store',$id) }}" method="post">
#csrf
...
</form>
and in the controller
public function store(Request $request,$id)
{
dd($request);
return $request;
}

how to pass html checkbox arrays to controller in route laravel?

I have a problem with Laravel framework .... I Have an HTML array of checkboxes in my Laravel view file like below:
#foreach($jobs as $job)
<input type="checkbox" name="jobs[]" value="{{$user->id}}">
#endforeach
//$jobs variable pointing to read records from jobs table in database
I want to pass "jobs" element to my Controller from the route file But I don't want to use jQuery to do it. (Should be passed with Get Method].
How can I do it?
<form method="get" action="{{route('some.route')}}">
#foreach($jobs as $job) <input type="checkbox" name="jobs[]" value="{{$user->id}}">
#endforeach
<input type="submit" value="submit">
</form>
web.php
Route::get('some/route','yourcontroller#somemethod')->name('some.route')
yourcontroller.php
public function somemethod(Request $request){
dd($request->get('jobs'));
//you an store it in database now
}
As far as I can understand your question, in order to pass data from your input to the controller you need to have a <form> that contains it, and set your method attribute to GET. From there, you can make a Route that will accept a parameter.
Read the Routing docs here.

Passing parameter / variable through two controllers in Laravel difficulty

I have a Data model that I want people to be able to view individual records of and then edit/add data to. I have managed to get the view route working;
Route::get('/data/{data_token}', 'DataController#show');
Data_token, is a unique string. This then uses this DataController function;
Public function show($data) {
$data = Data::where('data_token',$data)->first();
return view('data.show', compact('data'))
}
After which I can display the data on the page, and have a form for editing (actually its for adding data that doesn't exist, but whatever, same principle right).
On the form on the data.show view, I am sending it to a different view;
Route::get('/data/{data_token}/edit', 'DataController#edit');
This can use the $request variable to return the forms values, but I can't relate it to the data row I was previously editing?
how do I get the {data_token} passed to the edit function of the controller?
Edit( adding route files)
Noticed I forgot the {'data_token'} in the post route.
/Begs forgiveness
I think you've misunderstood how the routes and controllers work. What you're looking at is a fairly simple CRUD setup like the following;
Route::get('/data/{data_token}', 'DataController#show');
Route::get('/data/{data_token}/edit', 'DataController#edit');
Route::post('/data/{data_token}/edit', 'DataController#update');
Now your controller would have;
public function show($dataToken) { ... }
public function edit($dataToken) { ... }
public function update($dataToken, Request $request) { ... }
Then you'd have your form on the edit view like so;
<form action="{{ route('DataController#update') }}" method="post">
Laravels router will always try to pass in the URI variables as arguments to the methods provided.
Providing that I have understood what you need, this should suffice.

Forms in Symfony2

I'm trying to create a simple search form in Symfony2.
This is my form:
<form action="/search" method="GET">
<div class="input-group">
<input type="text" name="q" class="form-control" placeholder="Search ...">
<span class="input-group-btn">
<button class="btn-u btn-u-lg" type="button"><i class="fa fa-search"></i></button>
</span>
</div>
</form>
So my question is, what is the syntax of the form action? Do I just enter in the exact file that receives it? Or do I need to call some kind of config file?
Another question is how do I handle the search in the controller?
Thanks in advance!
Please note that I'm a total noob in Symfony2 :)
EDIT:
How do I handle the request if I would like a nice url like this: ".../search/value" instead of ".../search?q=value"?
Here is my action:
/**
* #Route("/search/{value}", name="search")
*/
public function searchAction($value)
{
}
in your action you need to put the logical path of your controller to do so call the twig function {{path('you route alias')}} , I assume that you have already set your route configuration.
to handle search in controller that's will depend on you re own logic but in the general case you will have to get the searched word using the request object taht should be some think like that:
public function searchAction(Request $request){
$objet=$request->query->get("word");
//do staff
return $this->render('Your Bundle:views:searchResult.html.twig')
}
In the form action, you need to enter the route that points to your controller. For example if you have a route that is set up to point to "/search" which uses your searchController's search method, you'd have to write action="/search" so when a user submits this form it is going to point to your controller's method.
In your controller you can either grab the $_GET variable with the name of the input (by the way you need to add a name for your input field to be accessible via the request superglobals), or pass the value directly in your url and put an optional variable after your "/search".

Deleting data in Symfony2

I have delete options for each row like this. I successfully deleted the data using GET method but How to delete in POST/DELETE method using the same layout? Is GET method the safe way to delete?
To use the DELETE method the best way is to use a form with a POST method and then fake the DELETE using a _method field. The form can then set the CSS of the form to be display: inline; or display: inline-block;.
Your "delete button"
<form action="{{ path('your_path') }}" method="POST" class="delete-button-form>
<input name="_method" value="DELETE" type="hidden">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
Your css
form.delete-button-form {
display: inline-block;
}
You can see a fiddle of this layout here
You will also need to set the config to use the http method override which the docs cover better than I could. Taken from here
The _method functionality shown here is disabled by default in Symfony 2.2 and
enabled by default in Symfony 2.3. To control it in Symfony 2.2, you must call
Request::enableHttpMethodParameterOverride before you handle the request (e.g.
in your front controller). In Symfony 2.3, use the http_method_override option.
Is GET method the safe way to delete?
I don't think is safer to use GET, POST, or DELETE. Whatever method you use, you still have to add rules in the firewall or in the controller to ensure that an user has the right to delete something.
You can declare a specific route for deleting an instance of your entity, without using any form:
/**
* #Route(
* "/something/{id}/delete",
* name="something_delete"
* )
*/
public function somethingRemoveAction($id)
{
$something = $this->getDoctrine()
->getRepository('ACMEBundle:Something')
->find($id);
$em = $this->getDoctrine()->getManager();
$em->remove($something);
$em->flush();
// Suggestion: add a message in the flashbag
// Redirect to the table page
return $this->redirect($this->generateUrl('something_list'));
}
Then create a button for each row of the table:
<a href="{{ path('something_delete', {'id': something.id}) }}">
<button type="button">Delete</button></a>

Categories