by Enrico Zimuel
Senior Software Engineer
Zend, a Rogue Wave Company (USA)
ApiConf, Turin, 15th June 2017
|
Released: 3 December 2015
Previous major was PHP 5, 13 July 2004
Skipped PHP 6: Unicode failure
Last release is 7.1.6 (8 Jun 2017)
$a = [];
for ($i = 0; $i < 1000000; $i++) {
$a[$i] = ["hello"];
}
echo memory_get_usage(true);
PHP 5.6 | PHP 7 | |
Memory Usage | 428 MB | 33 MB |
Execution time | 0.49 sec | 0.06 sec |
Request:
GET /api/version
Response:
HTTP/1.1 200 OK
Connection: close
Content-Length: 17
Content-Type: application/json
{
"version": "1.0"
}
A function that gets a request and generates a response
use Psr\Http\Message\ServerRequestInterface as Request;
use Interop\Http\ServerMiddleware\DelegateInterface;
function (Request $request, DelegateInterface $next)
{
// doing something with $request...
// for instance calling the delegate middleware $next
$response = $next->process($request);
// manipulate the $response
return $response;
}
This is called lambda middleware.
namespace Interop\Http\ServerMiddleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
interface DelegateInterface
{
/**
* @return ResponseInterface;
*/
public function process(ServerRequestInterface $request);
}
DelegateInterface is part of PSR-15 HTTP Middleware proposal
The PHP framework for Middleware applications
You can install Expressive 2.0 using composer:
composer create-project zendframework/zend-expressive-skeleton api
Choose the default options during the installation
The skeleton has 2 URL as example: / and /api/ping
The routes are registered in /config/routes.php
The middleware actions are stored in /src/App/Action
$app->get('/', App\Action\HomePageAction::class, 'home');
$app->get('/api/ping', App\Action\PingAction::class, 'api.ping');
/config/routes.php
namespace App\Action;
use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Zend\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ServerRequestInterface;
class PingAction implements MiddlewareInterface
{
public function process(
ServerRequestInterface $request,
DelegateInterface $delegate
) {
return new JsonResponse(['ack' => time()]);
}
}
/src/App/Action/PingAction.php
$app->pipe(ErrorHandler::class);
$app->pipe(ServerUrlMiddleware::class);
$app->pipeRoutingMiddleware();
$app->pipe(ImplicitHeadMiddleware::class);
$app->pipe(ImplicitOptionsMiddleware::class);
$app->pipe(UrlHelperMiddleware::class);
$app->pipeDispatchMiddleware();
$app->pipe(NotFoundHandler::class);
/config/pipeline.php
use Zend\ServiceManager\Config;
use Zend\ServiceManager\ServiceManager;
$config = require __DIR__ . '/config.php';
$container = new ServiceManager();
$config = new Config($config['dependencies']);
$config->configureServiceManager($container);
$container->setService('config', $config);
return $container;
/config/container.php
chdir(dirname(__DIR__));
require 'vendor/autoload.php';
call_user_func(function () {
$container = require 'config/container.php';
$app = $container->get(\Zend\Expressive\Application::class);
require 'config/pipeline.php';
require 'config/routes.php';
$app->run();
});
/public/index.php
$app->route('/api/users[/{user-id}]', [
Authentication\AuthenticationMiddleware::class,
Authorization\AuthorizationMiddleware::class,
Api\Action\UserAction::class
], ['GET', 'POST', 'PATCH', 'DELETE'], 'api.users');
// or route each HTTP method
$app->get('/api/users[/{user-id}]', ..., 'api.users.get');
$app->post('/api/users', ..., 'api.users.post');
$app->patch('/api/users/{user-id}', ..., 'api.users.patch');
$app->delete('/api/users/{user-id}', ..., 'api.users.delete');
use Psr\Http\Message\ServerRequestInterface;
use Interop\Http\ServerMiddleware\DelegateInterface;
trait RestDispatchTrait
{
public function process(
ServerRequestInterface $request,
DelegateInterface $delegate
) {
$method = strtolower($request->getMethod());
if (method_exists($this, $method)) {
return $this->$method($request);
}
return $response->withStatus(501); // Method not implemented
}
}
class UserAction implements MiddlewareInterface
{
use RestDispatchTrait;
public function get(ServerRequestInterface $request)
{
$id = $request->getAttribute('user-id', false);
$data = (false === $id) ? /* all users */ : /* user id */;
return new JsonResponse($data);
}
public function post(ServerRequestInterface $request){ ... }
public function patch(ServerRequestInterface $request){ ... }
public function delete(ServerRequestInterface $request){ ... }
}
Api\Action\UserAction.php
More info: https://framework.zend.com/blog
Contact me: enrico.zimuel [at] roguewave.com
Follow me: @ezimuel
This work is licensed under a
Creative Commons Attribution-ShareAlike 3.0 Unported License.
I used reveal.js to make this presentation.