可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I will destroy my user with a HTML link, but it doesn't seem to generate the correct link, what am i doing wrong?
public function destroy($id)
{
//Slet brugeren
$e = new User($id);
$e->destroy();
//Log også brugeren ud
Auth::logout();
//redrect til forsiden
Redirect::to("users/create");
}
In my view i call this
{{URL::action('UserController@destroy', array($user->id))}}
回答1:
Update 08/21/2017 for Laravel 5.x
The question asks about Laravel 4, but I include this in case people looking for Laravel 5.x answers end up here. The Form helper (and some others) aren't available as of 5.x. You still need to specify a method on a form if you are doing something besides GET or POST. This is the current way to accomplish that:
<form action="/foo/bar" method="POST">
<input type="hidden" name="_method" value="PUT">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<!-- other inputs... -->
</form>
You can also use {{ method_field('PUT') }}
instead of writing out the hidden _method
input.
See https://laravel.com/docs/5.4/routing#form-method-spoofing
Original Answer for Laravel 4
I think when you click the link, it is probably sending a GET request to that end point. CRUD in Laravel works according to REST. This means it is expecting a DELETE request instead of GET.
Here's one possibility from a tutorial by Boris Strahija.
{{ Form::open(array('route' => array('admin.pages.destroy', $page->id), 'method' => 'delete')) }}
<button type="submit" class="btn btn-danger btn-mini">Delete</button>
{{ Form::close() }}
This way, you send the request in a form with the DELETE method. The article explains why a traditional link won't work:
You may notice that the delete button is inside a form. The reason for this is that the destroy() method from our controller needs a DELETE request, and this can be done in this way. If the button was a simple link, the request would be sent via the GET method, and we wouldn’t call the destroy() method.
回答2:
An cool ajax solution that works is this:
function deleteUser(id) {
if (confirm('Delete this user?')) {
$.ajax({
type: "DELETE",
url: 'users/' + id, //resource
success: function(affectedRows) {
//if something was deleted, we redirect the user to the users page, and automatically the user that he deleted will disappear
if (affectedRows > 0) window.location = 'users';
}
});
}
}
<a href="javascript:deleteUser('{{ $user->id }}');">Delete</a>
And in the UserController.php we have this method:
public function destroy($id)
{
$affectedRows = User::where('id', '=', $id)->delete();
return $affectedRows;
}
回答3:
Another "clean" solution is to make it the Rails way as described here:
Create a new .js file in public and write this function:
$(function(){
$('[data-method]').append(function(){
return "\n"+
"<form action='"+$(this).attr('href')+"' method='POST' style='display:none'>\n"+
" <input type='hidden' name='_method' value='"+$(this).attr('data-method')+"'>\n"+
"</form>\n"
})
.removeAttr('href')
.attr('style','cursor:pointer;')
.attr('onclick','$(this).find("form").submit();');
});
Don't forget to include the .js file in your template after including jQuery.
Use classic link_to()
or link_to_method()
functions to create links to delete records. Just remember to include the "data-method"="DELETE"
parameter:
{{ link_to_route('tasks.destroy', 'D', $task->id, ['data-method'=>'delete']) }}
What I like about this that it seems much cleaner than bloating your code with Form::open();
in blade templates.
回答4:
For those looking to create the delete button in Laravel 5:
{!! Form::open(['action' => ['UserController@destroy', $user->id], 'method' => 'delete']) !!}
{!! Form::submit('Delete', ['class'=>'btn btn-danger btn-mini']) !!}
{!! Form::close() !!}
This is similar to Tayler's answer but we use the new blade escape tags ( {!!
and !!}
), we use the Form
facade to generate the button and we use a more elegant approach to link to the controller.
In Laravel < 5 the Forms & HTML package was pulled in automatically. In Laravel 5 we must add this package to composer.json
:
...
"required": {
...
"laravelcollective/html": "^5.1"
}
...
Now add the Service Provider and Alias in config/app.php
:
...
'providers' => [
...
Collective\Html\HtmlServiceProvider::class,
],
'aliases' => [
...
'Form' => Collective\Html\FormFacade::class,
'Html' => Collective\Html\HtmlFacade::class,
],
The above will output
<form method="POST" action="https://yourdomain.tld/users/1" accept-charset="UTF-8">
<input name="_method" type="hidden" value="DELETE">
<input name="_token" type="hidden" value="xxxCrAZyT0K3nsTr!NGxxx">
<input class="btn btn-danger btn-mini" type="submit" value="Delete">
</form>
If you are using a different form builder just make sure it generates something similar to the above.
回答5:
This is an old questions, but I was just looking for a quick answer and am not satisfied with any of these. What I would suggest to anyone with this same problem is create a new route. Worrying too much about crud compliance is silly, because there is no such thing over HTML; any solution is just shoe-horned to fit, whether it's a hidden form field or a get route.
So, in your routes, you likely have something like this:
Route::resource('users', 'UsersController');
The problem with this is that the only way to get to the "destroy" method is to sent a post request which has a hidden input named "_method" and a value of "DELETE".
Simply add under that line:
Route::get('users/{id}/destroy',['as'=>'users.delete','uses'=>'UsersController@destroy']);
Now you have a route you can access from HTML::linkRoute
, Route::url
, or whatever method you please.
For example:
{{ HTML::linkRoute( 'users.delete', 'Delete' , [ 'id' => $user->id ]) }}
EDIT
I want to clarify, though I have explained why it's somewhat silly to bend over backward to fit crud compliance, it is still true that your app will be more secure if changes are made only through POST requests.
回答6:
Want to send a DELETE request when outside of a form?
Well, Jeffrey Way created a nice javascript that creates a form for you and to use it you only need to add data-method="delete"
to your delete links.
To use, import script, and create a link with the data-method="DELETE"
attribute.
script :
(function() {
var laravel = {
initialize: function() {
this.methodLinks = $('a[data-method]');
this.registerEvents();
},
registerEvents: function() {
this.methodLinks.on('click', this.handleMethod);
},
handleMethod: function(e) {
var link = $(this);
var httpMethod = link.data('method').toUpperCase();
var form;
// If the data-method attribute is not PUT or DELETE,
// then we don't know what to do. Just ignore.
if ( $.inArray(httpMethod, ['PUT', 'DELETE']) === - 1 ) {
return;
}
// Allow user to optionally provide data-confirm="Are you sure?"
if ( link.data('confirm') ) {
if ( ! laravel.verifyConfirm(link) ) {
return false;
}
}
form = laravel.createForm(link);
form.submit();
e.preventDefault();
},
verifyConfirm: function(link) {
return confirm(link.data('confirm'));
},
createForm: function(link) {
var form =
$('<form>', {
'method': 'POST',
'action': link.attr('href')
});
var token =
$('<input>', {
'type': 'hidden',
'name': 'csrf_token',
'value': '<?php echo csrf_token(); ?>' // hmmmm...
});
var hiddenInput =
$('<input>', {
'name': '_method',
'type': 'hidden',
'value': link.data('method')
});
return form.append(token, hiddenInput)
.appendTo('body');
}
};
laravel.initialize();
})();
回答7:
For those looking to create delete button using anchor tag in laravel 5.
{!! Form::open(['action' => ['UserController@destroy', $user->id], 'method' => 'DELETE', 'name' => 'post_' . md5($user->id . $user->created_at)]) !!}
<a href="javascript:void(0)" title="delete" onclick="if (confirm('Are you sure?')) { document.post_<?= md5($user->id . $user->created_at) ?>.submit(); } event.returnValue = false; return false;">
<span class="icon-remove"></span>
</a>
{!! Form::close() !!}
回答8:
I tried your code, used it like this and worked:
<a href="{{URL::action('UserController@destroy',['id'=>$user->id]) }}"
onclick=" return confirm('Are you sure you want to delete this?')"
class="btn btn-default">
DELETE </a>
I think that the only problem is in your array:
['id'=>$user->id]
回答9:
{{Form::open(['method'=>'delete','action'=>['ResourceController@destroy',$resource->id]])}}
<button type="submit">Delete</button>
{{Form::close()}}