CRUD Laravel 5 how to link to destroy of Resource

2019-01-23 13:11发布

问题:

I have a link

<a class="trashButton" href="{{ URL::route('user.destroy',$members['id'][$i]) }}" style="cursor: pointer;"><i class="fa fa-trash-o"></i></a> 

this link is supposed to direct to the destroy method of the Usercontroller , this is my route Route::resource('/user', 'BackEnd\UsersController');

UserController is a Resource Controller. But at this moment it is directing me to the show method rather than directing to the destroy method

回答1:

This is because you are requesting the resources via GET method instead DELETE method. Look:

DELETE  /photo/{photo}  destroy     photo.destroy
GET     /photo/{photo}  show    photo.show

Both routes have the same URL, but the header verb identifies which to call. Looks the RESTful table. For example, via ajax you can send a DELETE request:

$.ajax({
    url: '/user/4',
    type: 'DELETE',  // user.destroy
    success: function(result) {
        // Do something with the result
    }
});


回答2:

You need to send a DELETE request instead of a GET request. You can't do that with a link, so you have to use an AJAX request or a form.

Here is the generic form method:

<form action="{{ URL::route('user.destroy', $members['id'][$i]) }}" method="POST">
    <input type="hidden" name="_method" value="DELETE">
    <input type="hidden" name="_token" value="{{ csrf_token() }}">
    <button>Delete User</button>
</form>

If you're using Laravel 5.1 or later then you can use Laravel's built-in helpers to shorten your code:

<form action="{{ route('user.destroy', $members['id'][$i]) }}" method="POST">
    {{ method_field('DELETE') }}
    {{ csrf_field() }}
    <button>Delete User</button>
</form>

If you're using Laravel 5.6 or later then you can use the new Blade directives to shorten your code even further:

<form action="{{ route('user.destroy', $members['id'][$i]) }}" method="POST">
    @method('DELETE')
    @csrf
    <button>Delete User</button>
</form>

You can read more about method spoofing in Laravel here.



回答3:

I use this template 'resources/views/utils/delete.blade.php'

<form action="{{ $url or Request::url() }}" method="POST">
    {{ method_field('DELETE') }}
    {{ csrf_field() }}
    <button type='submit' class="{{ $class or 'btn btn-danger' }}" value="{{ $value or 'delete' }}">{!! $text or 'delete' !!}</button>
</form>

Called as this:

@include('utils.delete',array( 'url' => URL::route('user.destroy',$id),'text' => '<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> delete me'))


回答4:

If you're looking to do this via a regular link instead of through AJAX or another type of form request you can set up a special route that will respond to a normal GET request:

In your routes, define this in addition to the resource:

Route::get('user/{site}/delete', ['as' => 'user.delete', 'uses' => 'UserController@destroy']);

In your view:

<a href="{{ route('user.delete', $user->id) }}">Delete this user</a>

In your controller:

public function destroy(User $user)
{
  $user->delete();
  return redirect()->route('users.index');
}


回答5:

If we need to use an anchor to trigger the destroy route, and we don't want to use ajax, we can put a form inside our link, and submit the form using the onclick attribute:

<a href="javascript:void(0);" onclick="$(this).find('form').submit();" >
    <form action="{{ url('/resource/to/delete') }}" method="post">
        <input type="hidden" name="_method" value="DELETE">
    </form>
</a>


回答6:

If you really want to visit the destroy action on delete route by HTML, then there is an approach to use HTTP Method Spoofing which means that you could visit a delete HTTP method by adding a hidden input named _method with the value of `"DELETE". Same way can be used for "PUT" and "PATCH" HTTP method.

Below is a sample for DELETE method.

<form action="/tasks/5" method="POST">
<input type="hidden" name="_method" value="DELETE">
</form>

will get the route

DELETE  /tasks/{id}  destroy     tasks.destroy

if you use laravel collective, you can write this way in your views.

{!! Form::open(['url' => '/tasks/'.$cat->id, 'method' => 'delete']) !!}
{!! Form::submit('Delete', ['class' => 'btn btn-primary']) !!}
{!! Form::close() !!}


回答7:

If you want to use a link, you can use a library I have created that lets people make links that behave like POST, DELETE... calls.

https://github.com/Patroklo/improved-links



回答8:

In case someone came here to find how to replace standard laravel form for delete, from button in it to link, you can just replace:

{!! Form::open(['method' => 'DELETE', 'route' => ['tasks.destroy', $task->id],'onsubmit' => 'return confirm("Are you sure?")', 'id'=>'himan']) !!}

    {!! Form::submit('Delete') !!}

{!! Form::close() !!}

TO

{!! Form::open(['method' => 'DELETE', 'route' => ['tasks.destroy', $task->id],'onsubmit' => 'return confirm("Are you sure?")', 'id'=>'himan']) !!}

    <a href="#" onclick="$(this).closest('form').submit();">Delete</a>

{!! Form::close() !!}

Just replace button with simple <a href="#"... but with onclick attribute to submit the form!



回答9:

GET and DELETE Both routes have the same URL, but the header verb identifies which to call.

Here are my code snippets for edit and delete. I use bootstrap modal confirmation for delete action

<div class="btn-group">
  <a href="{{ route('locations.edit', $location->id) }}"
   class="btn btn-default btn-sm">
    <i class="fa fa-pencil"></i>
  </a>
  <span class="btn btn-danger btn-sm formConfirm"
      data-form="#frmDelete-{{$location->id}}"
      data-title="Delete Location"
      data-message="Are you sure you want to delete this Location ?">
      <i class="fa fa-times"></i>
  </span>
<form method="POST"
      style="display: none"
      id="frmDelete-{{$location->id}}"
      action="{{ route('locations.destroy' , $location->id) }}">
    {!! csrf_field() !!}
    {{ method_field('DELETE') }}
    <input type="submit">
</form>

BootStrap Modal

<div class="modal fade" id="formConfirm" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span
                        class="sr-only">Close</span></button>
            <h4 class="modal-title" id="frm_title">Delete</h4>
        </div>
        <div class="modal-body" id="frm_body"></div>
        <div class="modal-footer">
            <button style='margin-left:10px;' type="button" class="btn btn-primary col-sm-2 pull-right"
                    id="frm_submit">Yes
            </button>
            <button type="button" class="btn btn-danger col-sm-2 pull-right" data-dismiss="modal" id="frm_cancel">
                No
            </button>
        </div>
    </div>
</div>

And Finally JS code

$('.formConfirm').on('click', function (e) {
  e.preventDefault();
  var el = $(this);
  var title = el.attr('data-title');
  var msg = el.attr('data-message');
  var dataForm = el.attr('data-form');

  $('#formConfirm')
    .find('#frm_body').html(msg)
    .end().find('#frm_title').html(title)
    .end().modal('show');

  $('#formConfirm').find('#frm_submit').attr('data-form', dataForm);
});

$('#formConfirm').on('click', '#frm_submit', function (e) {
  var id = $(this).attr('data-form');
  $(id).submit();
});


回答10:

My, non-ajax version. I use it in dropdowns (bootstrap) in resource list (datatables as well). Very short and universal.

Global jQuery method:

$('.submit-previous-form').click(function (e) {
    e.preventDefault();
    $($(this)).prev('form').submit();
});

And then we can use everywhere something like this:

{{ Form::open(['route' => ['user.destroy', $user], 'method' => 'delete']) }} {{ Form::close() }}
<a href="#" class="dropdown-item submit-previous-form" title="Delete user"><i class="icon-trash"></i> Delete him</a>

Recommend: It's easy to integrate with confirms scripts for example swal.