Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building A RESTful API With Laravel

Building A RESTful API With Laravel

Saad El Hajjaji

March 15, 2015
Tweet

Other Decks in Programming

Transcript

  1. Constraints Building a RESTful API • Uniform Interface • Stateless

    HTTP Verbs / URIs / HTTP Responses • Client-Server • Cacheable • Layered System Server Responses • Code On Demand
  2. Action Plan Users - Create - Read - Update -

    Delete - List - Posts - Comments Posts - Create - Read - Update - Delete - List - Comments Comments - Create - Read - Update - Delete - List
  3. Status Codes 200: Success! 201: Resource created 204: Success, but

    no content to return 400: Request not fulfilled 401: Not authenticated 403: Refusal to respond 404: Not found 500: Other error
  4. The Direct Approach <?php class PostController extends Controller { public

    function show($id) { return json_encode([ 'data' => Post::find($id)->toArray(), ]); } public function index() { return json_encode([ 'data' => Post::all()->toArray(), ]); } }
  5. Formatting Data <?php class PostController extends Controller { public function

    show($id) { $post = Post::find($id); return json_encode([ 'data' => [ 'id' => (int) $post->id, 'title' => $post->title, 'content' => $post->content, 'created_at' => (string) $post->created_at, ], ]); } }
  6. Fractal Output complex, flexible, AJAX/RESTful data structures. $ composer require

    league/fractal 1. Create Transformers 2. Create ApiController
  7. Fractal Output complex, flexible, AJAX/RESTful data structures. $ composer require

    league/fractal 1. Create Transformers 2. Create ApiController 3. Update Controllers
  8. <?php namespace App\Transformers; use App\Post; use League\Fractal\TransformerAbstract; class PostTransformer extends

    TransformerAbstract { public function transform(Post $post) { return [ 'id' => (int) $post->id, 'content' => $post->content, 'created_at' => (String) $post->created_at, ]; } }
  9. ApiController class ApiController extends Controller { protected $statusCode = 200;

    public function __construct(Manager $fractal) { $this->fractal = $fractal; } protected function respondWithItem($item, $callback) { //Create item then return it with respondWithArray() } protected function respondWithCollection($collection, $callback){ //Create Collection then return it with respondWithArray() } protected function respondWithArray(array $array, array $headers = []) { $response = response()->json($array, $this->statusCode, $headers); return $response; }
  10. ApiController protected function respondWithError($message, $errorCode) { return $this->respondWithArray([ 'error' =>

    [ 'code' => $errorCode, 'http_code' => $this->statusCode, 'message' => $message, ] ]); } }
  11. Update Controllers class PostController extends ApiController { public function index()

    { $posts = Post::take(10)->get(); return $this->respondWithCollection($posts, new PostTransformer); } public function show($id) { $post = Post::find($id); return $this->respondWithItem($post, new PostTransformer); } }
  12. Resource Groups Action Create Read Update Delete List Endpoint POST

    /posts GET /posts/X PUT /posts/X DELETE /posts/X GET /posts
  13. POST /posts public function store(Request $request) { $post = new

    Post(); $post->content = $request->content; $post->user = User::find($request->user_id); $post->save(); return response()->json([ "msg" => "Success", "id" => $post->id() ], 200 ); }
  14. PUT /posts/X public function update(Request $request, $id) { $post =

    Post::find($id); $post->content = $request->content; $post->user = User::find($request->user_id); $post->save(); return response()->json([ "msg" => "Success", ], 200 ); }
  15. DELETE /posts/X public function destroy($id) { $post = Post::find($id); $post->delete();

    return response()->json([ "msg" => "Success", ], 200 ); }
  16. class ApiController extends Controller { const CODE_WRONG_ARGS = 'GEN-1WT45PO'; const

    CODE_NOT_FOUND = 'GEN-LPF2FV6'; const CODE_INTERNAL_ERROR = 'GEN-A9AR4H'; const CODE_UNAUTHORIZED = 'GEN-M36UI'; const CODE_FORBIDDEN = ‘GEN-23T7'; protected function respondWithError($message, $errorCode) { return $this->respondWithArray([ 'error' => [ 'code' => $errorCode, 'http_code' => $this->statusCode, 'message' => $message, ] ]); } public function errorNotFound($message = 'Resource Not Found') { return $this->setStatusCode(404)->respondWithError($message, self::CODE_NOT_FOUND); } public function errorUnauthorized($message = 'Unauthorized') { return $this->setStatusCode(401)->respondWithError($message, self::CODE_UNAUTHORIZED); } //errorForbidden, errorInternalError, …
  17. Foreign Key Arrays { "post": { "id": 1 "title": "Progressive

    Enhancement is Dead", "comments": ["1", "2"], "_links": { "user": "/people/saadel" } } }
  18. Embedded Documents <?php namespace App\Transformers; use … class PostTransformer extends

    TransformerAbstract { protected $availableEmbeds = [ 'user', 'comments' ]; public function transform(Post $post) { //Formatting our data } public function embedComments(Post $post) { $comments = $post->comments; return $this->collection($comments, new CommentTransformer); } // embedUser… }
  19. Resources Build APIs you won’t hate by Phil Sturgeon REST

    API Design Rulebook by Mark Masse REST API concepts and examples