Building Middleware Web APIs
in PHP 7 with Expressive

by Matthew Weier O'Phinney and Enrico Zimuel
Zend Framework Team
Rogue Wave Software, Inc.


ZendCon 2017, Las Vegas (NV), Oct. 23

Building Web APIs

Building a Web API

  • Managing the HTTP request and response
  • Choosing a representation format
  • Choosing an error format
  • Filtering & validating input data
  • Authenticating HTTP requests
  • Authorizing HTTP requests

Middleware

CORE CONCEPTS

  • PSR-7: provides our HTTP request and response messages
  • Request Handlers / Delegates: turn a request into a response
  • Middleware: intercepts a request and optionally delegates creation of a response

REQUEST HANDLERS / Delegates


// What we'll use
public function process(
	ServerRequestInterface $request
) : ResponseInterface

// Current PSR-15
public function handle(
	ServerRequestInterface $request
) : ResponseInterface

MIDDLEWARE INTERFACE


// What we'll use
public function process(
    ServerRequestInterface $request,
    DelegateInterface $delegate
) : ResponseInterface

// Current PSR_15
public function process(
    ServerRequestInterface $request,
    RequestHandlerInterface $delegate
) : ResponseInterface

DELEGATION


// DelegateInterface:
$response = $delegate->process($request);

// RequestHandlerInterface
$response = $delegate->handle($request);

MIDDLEWARE AS REQUEST HANDLERS


public function process(ServerRequest $request, Delegate $delegate)
{
    $item = $this->repository->fetchById(
        $request->getAttribute('id')
    );
    return new JsonResponse($item);
}

WHY USE MIDDLEWARE?

  • To fill out HTTP web server functionality
  • To create custom application workflows
  • To facilitate web API development

HANDS ON

USE CASE

  • Develop a web API for reviewing books
  • A user logs in to the application, and can review any book
  • A user can modify only the review that he/she created

INGREDIENTS

TOOLS

DB SCHEMA: Users


CREATE TABLE user (
    username VARCHAR(80) PRIMARY KEY,
    password VARCHAR(100) NOT NULL,
    role VARCHAR(80) DEFAULT 'user'
);
          

DB SCHEMA: Books


CREATE TABLE book (
    id BINARY PRIMARY KEY,
    title VARCHAR(80),
    author VARCHAR(80),
    publisher VARCHAR(80),
    pages INT NULL,
    year INT NOT NULL,
    isbn VARCHAR(13) UNIQUE NULL
);
          

DB SCHEMA: Reviews


CREATE TABLE review (
    id BINARY PRIMARY KEY,
    username VARCHAR(80) NOT NULL,
    book_id BINARY NOT NULL,
    review TEXT NOT NULL,
    stars INT NOT NULL
);
          

Repository

git clone https://github.com/ezimuel/zendcon2017-api-tutorial

APIs completed

  • GET /books
  • GET /books/{id}
  • GET /reviews
  • GET /reviews/{id}
  • POST /reviews *
  • PATCH /reviews/{id} *

* user authentication required

APIs to be completed

  • POST /books *
  • PATCH /books/{id} *
  • DELETE /reviews/{id} *
  • GET /users **
  • GET /user/{username} **
  • POST /users **
  • PATCH /users/{username} **
  • DELETE /users/{username} **

* user authentication required, ** only admin

Thanks!

More info at
https://docs.zendframework.com/zend-expressive/