RESTful deleting in Laravel

Restfull deleting in Laravel can make newcomers to RESTful APIs scratch their head a bit. I know, cause I'm one of them. We're used to just have a simple link pointing to a certain URI where the magic happens, but how do we set the HTTP verb if we're not submitting any 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. Smooth and clean, as always, but no CSRF handling unless you include the javascript directly in your views with a <script> tag. Zizaco, creator of Confide and Entrust also has a solution, but also - no CSRF handling. So I thought, if these two guys didn't come up with a way to handle CSRF tokens, I'm not even going to try. I'll just do a quick'n'dirty fix, which is not nearly as elegant as theirs, but it does have that sweet CSRF token we all want.

Keeping it as simple as it can get, we'll create a macro. If you don't have one already, create the file /app/macros.php:


/*
|--------------------------------------------------------------------------
| Delete form macro
|--------------------------------------------------------------------------
|
| This macro creates a form with only a submit button. 
| We'll use it to generate forms that will post to a certain url with the DELETE method,
| following REST principles.
|
*/
Form::macro('delete',function($url, $button_label='Delete',$form_parameters = array(),$button_options=array()){

    if(empty($form_parameters)){
        $form_parameters = array(
            'method'=>'DELETE',
            'class' =>'delete-form',
            'url'   =>$url
            );
    }else{
        $form_parameters['url'] = $url;
        $form_parameters['method'] = 'DELETE';
    };

    return Form::open($form_parameters)
            . Form::submit($button_label, $button_options)
            . Form::close();
});

And than load it in /app/start/global.php like so:

require app_path().'/macros.php';

In your blade templates you generate the link like this:

{{Form::delete('resource/'. $resource->id, 'Delete')}}

Simple enough, right? You can comlicate it a bit adding more parameters for more control.

{{Form::delete('resource/'. $resource->id, 
                'Delete',
                array('id'=>'the_form_id','class' => 'the-delete-form'),
                array('class'=>'the-delete-link')
                )}}

Not that sleek, but functional.

And in the end let's ask the user if he really really wants to delete the resource:

$(document).on('submit', '.delete-form', function(){
    return confirm('Are you sure?');
});

That's what I got. Here's the gist, please feel free to fork it and let me know how we can make it better.

comments powered by Disqus