This document discusses building REST APIs with Laravel 5. It covers topics like using REST instead of SOAP, authentication with basic authentication and middleware, response formats, controller hierarchy, repositories, data transformers, error handling, and an internal dispatcher for making internal API requests. The goal is to provide best practices and patterns for building robust and well-structured REST APIs with Laravel.
10. Response format
HTTP/1.1 200 OK
Content-Type: application/json
Connection: close
X-Powered-By: PHP/5.6.3
Cache-Control: no-cache
Date: Fri, 13 Apr 2015 16:37:57 GMT
Transfer-Encoding: Identity
{"status":true,"data":{"k1":"value1","k2":"value2"},"message":"Zero imagination for funny
messages"}
11. Most common HTTP status codes
• 200 OK
• 201 Created
• 204 No Content
• 400 Bad Request
• 401 Unauthorized
• 403 Forbidden
• 404 Not Found
• 409 Conflict
• 500 Internal Server Error
12. Response message format
{
"status": true,
"data": {
"k1": "value1",
"k2": "value2"
},
"message": "Zero imagination for funny messages"
}
{
"status": false,
"errors": {
"e1": "Nope, it can't be done",
"e2": "That can't be done either"
},
"error_code": 12345,
"message": "Zero imagination for funny messages"
}
14. app/Http/Controllers/ApiController.php
<?php
namespace AppHttpControllers;
use IlluminateHttpRequest;
use IlluminateRoutingResponseFactory;
use IlluminateAuthGuard;
use AppUser;
class ApiController extends Controller{
public $response;
public $request;
public $auth;
public function __construct(ResponseFactory $response, Request $request, Guard $auth)
{
$this->response = $response;
$this->request = $request;
$this->auth = $auth;
$this->currentUser = $this->auth->user();
}
}
15. app/Http/Controllers/ApiController.php
public function respond($data, $response_message, $status_code = 200) {
//If this is an internal request we only return the data
if ($this->request->input('no-json'))
return $data;
$message['status'] = true;
if (isset($data))
$message['data'] = $data;
if (isset($message))
$message['message'] = $response_message;
if (isset($error_code))
$message['error_code'] = $error_code;
return $this->response->json($message, $status_code);
}
26. app/Repositories/BaseRepository.php
<?php
namespace AppRepositories;
use IlluminateDatabaseEloquentModel;
class BaseRepository {
public function __construct(Model $model) {
$this->model = $model;
}
public function create($data)
{
return $this->model->create($data);
}
public function find($id)
{
return $this->model->find($id);
}
public function delete($id)
{
return $this->model->destroy($id);
}
public function all()
{
return $this->model->all();
}
27. app/Repositories/BaseRepository.php
public function update($record, $data)
{
if (is_int($record)){
$this->model->find($record);
$id = $record;
} else {
$this->model = $record;
$id = $record->id;
}
return $this->model->where('id',$id)->update($data);
}
public function getById($id, $user_id = null, $with = null)
{
if (is_array($id)){
$result = $this->model->whereIn('id', $id);
}else{
$result = $this->model->where('id', $id);
}
if ($user_id)
$result->where('user_id', $user_id);
if ($with)
$result->with($with);
if (is_array($id)){
return $result->get();
return $result->first();
}
36. STATUS 404 Not Found
{
"status": false,
"error_code": 1235,
"errors": [
"We don't have that kind of resources"
]
}
STATUS 404 Not Found
{
"status": false,
"error_code": 2234,
"errors": [
"That resource doesn't exist"
]
}
STATUS 418 I'm a teapot
{
"status": false,
"message": "I'm a teapot"
}
STATUS 500 Internal Server Error
{
"status": false,
"message": "Class 'User' not found"
}
38. <?php
namespace AppHttp;
class InternalDispatcher {
public function release( $url, $method = 'GET', $input, $no_json) {
// Store the original input of the request
$originalInput = Request::input();
// Create request to the API, adding the no-json parameter, since it's an internal request
$request = Request::create($url, $method);
// Replace the input with the request instance input
Request::replace($input);
// Fetch the response
if ($no_json){
$content = Route::dispatch($request)->getContent();
$result = json_decode($content, 1);
}else{
$result = Route::dispatch($request)->getContent();
}
// Replace the input again with the original request input.
Request::replace($originalInput);
return $result;
}
public function withNoInput($url, $method = 'GET', $no_json = true){
$input = ['no-json'=>$no_json];
return $this->release($url, $method = 'GET', $input, $no_json);
}
}
app/Http/InternalDispatcher.php