Quick example of Laravel API POST route implementation
Tags: laravel, beginners
Published: 2020-07-23 11:27:14

Laravel provides an API middleware and routing out of the box, which enables us to set up REST APIs. We can then access the endpoints from our JavaScript layer, whether it’s vanilla JS or any frontend library/framework.

Problem is, I kept forgetting the exact syntax and workflow, especially for `POST` requests. 🤦‍♀️ Below are quick snippets demonstrating its most simple implementation. 

#### 1) public/js/main.js

```js
function testPostRoute(id = '') {
  fetch(`/api/foo/${id}`, {
    method: 'POST',
    headers: {
      "Content-type": "application/json", // We are sending JSON data
      credentials: 'include'
    },
    body: JSON.stringify({ name: 'Eka', isHungry: true })
  })
    .then(function(response) {
      return response.json();
    })
    .then(function (payload) {
      console.log("API response", payload);
      // ... do other things here
    })
}
```

- Here we make an API call to `/api/foo/123` where `123` is the id. I also set the method and headers like we normally do with REST API requests. I use the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), but any library should work.
- We send the stringified payload in the `body`, then we log the response payload.
- Note that this request is not a good RESTful practice. `POST` requests should be sent to the list of resources, eg. `/api/posts` (to create a new post); whereas `PUT` requests are sent to the single resource, eg. `/api/posts/123` (to update an existing post). I use this endpoint here to demonstrate how the Laravel API route URL slug parameter works.

#### 2) routes/api.php

```php
Route::post('foo/{id}', 'SomeController@foo');
```

- Here we set an API endpoint at `/api/foo/xxxx`, where `xxxx` is the dynamic route parameter whose value will be available in the variable `$id`. Omit the `/{id}` part if not necessary.
- Note that the endpoint is _automatically prefixed_ with `api`.
- We can set up routes with any HTTP verb, eg. `Route::get`, `Route::put`, etc.

#### 3) app/Http/Controllers/SomeController.php

```php
class SomeController extends Controller {
  public function foo(Request $request, $id)
  {
    $payload = json_decode($request->getContent(), true);
    try {
      // Get data here, eg. make an external API request or DB query
      $response = [
        'id' => $id,
        'name' => $payload['name']
      ];
    } catch (\GuzzleHttp\Exception\BadResponseException $e) {
      $errorResJson = $e
        ->getResponse()
        ->getBody()
        ->getContents();
      $errorRes = json_decode(stripslashes($errorResJson), true);
      // Return error
      return response()->json(
        [
          'message' => 'error',
          'data' => $errorRes
        ],
        $errorRes['response']['code']
      );
    }
    // Return success
    return response()->json(
      [
        'status' => '200',
        'data' => $response,
        'message' => 'success'
      ],
      200
    );
  }
}
```

- You can use any name for the controller and method names (here I use `SomeController` and `foo` respectively). Just make sure they are called correctly in routes/api.php.
- The method contains the [HTTP request](https://laravel.com/docs/7.x/requests) and the `$id` variable from the route. (If you omit the `{id}` from route setup above, this variable will not exist.)

---

Learn more about Laravel REST API:

- https://blog.pusher.com/build-rest-api-laravel-api-resources/
- https://www.toptal.com/laravel/restful-laravel-api-tutorial