EugeneB
EugeneB

Reputation: 21

Trying to use PATCH method works with AJAX but not with a regular html form

I'm currently trying out http://altorouter.com/ and it's working well for me so far, except for this one issue I'm having

My route is set up like this:

$router->map( 'PATCH', '/admin/pages', 'pageController@update');

If I use the following jquery, the route works perfectly:

$.ajax({
    type: "PATCH",
    url: "/admin/pages",
    data: {page_items:page_items, page_name: 'test_page'},
    success: function(returned_data)
    {
        console.log(returned_data);
    }
});

However, no matter what I put in my HTML I can't get a regular form to submit in a way it accepts as PATCH:

<form action="/admin/pages" method="post">
    <input type="hidden" name="form_function" value="edit_theme">
    <input type="hidden" name="_METHOD" value="PATCH">
    <button type="submit">Save Page</button>
</button>

I've tried "_METHOD", "_method", "method" etc. None of them work.

I've also tried

method="PATCH"

but that only causes it to do a GET.

When I echo the $_SERVER['REQUEST_METHOD'] on the target page I get "PATCH" for the ajax, but just "POST" for the form. Hope someone can help.

Upvotes: 2

Views: 1845

Answers (2)

EugeneB
EugeneB

Reputation: 21

Managed to find a working solution after digging around in the code. Altorouter's match method actually accepts a method parameter, which doesn't seem to be documented anywhere.

Where I used to have

$match = $router->match();

I now have:

if(isset($_POST['_method']))
{
    $match = $router->match(null, $_POST['_method']);
}
else
{
    $match = $router->match();
}

Upvotes: 0

Doug
Doug

Reputation: 1890

In short, you cannot.

As you'll see in the W3 Spec

The only valid methods for HTML based forms are "GET" and "POST".

However you can work around this if you wish, on the server side instead. Theres a great article about how Laravel does it here: Theres no Put/Patch Delete Methods

A quick snippet of code from that article:

<form method="POST" action="" accept-charset="UTF-8">
    <input name="_method" type="hidden" value="PUT">
</form>

<form method="POST" action="" accept-charset="UTF-8">
    <input name="_method" type="hidden" value="PUT">  
</form>

If you are not using Laravel and want to build a form manually, you cannot use PUT/PATCH – there’s just no such methods supported by forms in browsers – it’s only GET and POST. So how does Laravel make it work with {{ Form::create([‘method’ => ‘PUT’]) }}? Actually, under the hood the generated HTML looks like this:

That’s right, Laravel constructs a hidden field with name _method and then checks it upon form submittion, routing it to the correct Controller method.

So if for any reason you would need to build the FORM tag yourself, don’t put (same applied to patch and delete) – it just won’t work. Instead add hidden fields, if necessary.

So back to your issue, Altorouter. It appears their documentation is rather lacing the best guide I can find for you is here https://recalll.co/app/?q=rest%20-%20PHP%20detecting%20request%20type%20(GET%2C%20POST%2C%20PUT%20or%20DELETE)%20-%20Stack%20Overflow it might be worth your while finding a better router, as Alto doesn't seem to have been updated in around 3 years.

Upvotes: 0

Related Questions