Deleting data in Symfony2 - php

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>

Related

Laravel 9 html form submit throws 405. Expects PUT, request is GET

I'm trying to create a simple CRUD application with Laravel 9. I've run into a problem with HTML forms. I've created a page where you can edit data on rabbits existing in my database.
My form
<form name="editRabbitForm" action="{{ url('/rabbit/update') }}" method="PUT">
{{ csrf_field() }}
<!-- here be input fields -->
<button type="submit" class="btn btn-success">Save</button>
<a type="button" href="/rabbits" class="btn btn-danger">Cancel</a>
</form>
web.php routes
<?php
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\QuoteController;
use App\Http\Controllers\RabbitController;
use Illuminate\Support\Facades\Route;
Route::get('/rabbits', [RabbitController::class, 'index']);
Route::get('/rabbit/edit/{id}', [RabbitController::class, 'edit']);
Route::put('/rabbit/update', [RabbitController::class, 'update']);
RabbitController.php
<?php
namespace App\Http\Controllers;
use App\Models\Rabbit;
use Illuminate\Http\Request;
class RabbitController extends Controller
{
public function index() {
return view('rabbits.index', ['rabbits' => Rabbit::all()]);
}
public function edit($id) {
return view('rabbits.edit', ['rabbit' => Rabbit::where('breed_id', $id)->first()]);
}
public function update(Request $request) {
echo("SOME SORT OF RESULT!");
var_dump($request);
}
}
Before I even hit the controller I get an exception reading:
The GET method is not supported for this route. Supported methods: PUT.
I really don't get what I'm doing wrong in this scenario
As stated above in my comment:
To send a put request you will need to change the method to POST and add #method('PUT') in your form. This will insert a hidden input for the method. Laravel will then automatically route this request to the method specified by the put route in your routes file.
This is needed because as #ADyson writes, browsers are limited to GET and POST request.
And last but not least, browsers or in this case HTML forms are stupid.
Maybe someday this will be changed, who knows.

Laravel form best practice ? Hidden input OR Route parameter?

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.

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".

How does Joomla route to the controller method on submitting the form?

In a case where the form action is set to something like:
action="<?php echo JRoute::_('index.php?option=com_test&layout=edit&id='.(int) $this->item->id); ?>"
and the form contains and hidden input:
<input type="hidden" name="task" value="testctrl.save" />
How does joomla route to the controller method?
I would understand if it had the task in the form action, but I can't see how it picks up the task from the hidden input in order to route to the appropriate method in the testctrl controller method
It's not that complicated. In your com_mycom directory there is a file called mycom.php. In it you have some lines that look like this:
$controller = JControllerLegacy::getInstance('Contact');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
See an example here:
https://github.com/joomla/joomla-cms/blob/staging/components/com_contact/contact.php#L15
So that's what takes the task and instantiates an instance of that controller object, and pulls the task from the hidden form input value that you pointed out. It passes the task to the controller from there.
The controller receives the request here:
https://github.com/joomla/joomla-cms/blob/staging/components/com_contact/controller.php#L19
You might be asking "why don't I see it receiving the task that the component file sends it?". Well that's because the controller for this component is a child-class of the JControllerLegacy class:
https://github.com/joomla/joomla-cms/blob/staging/libraries/legacy/controller/legacy.php#L701
public function execute($task)
{ ... }
This function is the execute function which receives the task from the component. This is the parent class of your controller task. Hopefully this all makes sense!
When you set the controller name explicitly with hidden fields
<input type="hidden" name="task" value="testctrl.save" />
or
<input type="hidden" name="controller" value="testctrl" />
<input type="hidden" name="task" value="save" />
or even not specifying the controller with task , just used it with view name.
All the cases your component file like com_test have a file with test.php
it includes Joomla library files.
jimport('joomla.application.component.controller');
when you check the library file it have two function for getting related controller and models.
createFileName() and getInstance() in libraries/joomla/application/component/controller.php
These two function do the task.
The above files are applicable only for Joomla 1.5 to Joomla 2.x
Edit
For Joomla3.x
In Joomla 3. x The file structure little bit changed.
Instead of jimport('joomla.application.component.controller'); Joomla 3.x uses
$controller = JControllerLegacy::getInstance('Content');
This will call the JControllerLegacy class in libraries\legacy\controller\legacy.php
you can find the same functions createFileName() ,getInstance() on the above path.
Hope its helps..

CakePHP - REST POST functionality not working with default mapping

I am new to CakePHP and am attempting to configure my web app to use REST.
I am using CakePHP version 2.0.4.
Following the CakePHP Cookbook, I have entered the following into the routes.php file ('Apples' pointing to the ApplesController.php controller):
Router::mapResources('Apples');
Router::parseExtensions();
and in the controller itself (ApplesController.php), I have added the following component:
public $components = array('RequestHandler');
Also in the controller, I have an add action which echo's a string (as follows):
function add() {
echo 'The add action has been called';
}
Finally, I created a view (index.ctp located in app/View/apples/) which uses a HTML form with the method POST and the action "/apples/" to submit.
<h2>Home<h2>
<form action="/apples/" method="post">
<input type="submit" value="Submit" />
</form>
Now according to the the CakePHP Bakery (http://bakery.cakephp.org/articles/rightwayindia/2010/01/11/restful-web-application-development-in-cakephp), the mapResources should automatically map POST to the 'add' action of the controller specified in the routes.php file, therefore when the button is clicked, should echo the string in the add action.
This only works when you change the action parameter in the HTML (in index.ctp) to:
<form action="/apples/add" method="post">
and explicitly point to the add action.
I may be wrong, but I thought that by configuring REST in the routes.php file should automatically map the specific REST methods to the actions such as add, edit, delete etc.. (stated on the web page linked above) to the controller stated in the paramater of the mapResources function.
I have also tried custom REST routing but this is also not working. However, It would be nice for it to work with default mapping rather than customising it.
Any suggestions would be appreciated. Thanks.

Categories