by Enrico Zimuel / @ezimuel
						Senior Software Engineer
Zend Technologies, a Rogue Wave Company
					
						
Oct 18, ZendCon 2016, Las Vegas
					
 
							 
						 | 
						
							
  | 
					
GET /path HTTP/1.1
Host: example.com
Accept: application/json
				            
				          
HTTP/1.1 200 OK
Content-Type: application/json
{"foo":"bar"}
				            
				          But every framework does it differently.
$method = $request->getMethod();
$method = $request->getRequestMethod();
$method = $request->method;
				          
				        
				        
$method     = $request->getMethod();
$accept     = $request->getHeader('Accept');
$path       = $request->getUri()->getPath();
$controller = $request->getAttribute('controller');
				          
				        
$response->getBody()->write('Hello world!');
$response = $response->withStatus(200, 'OK')
            ->withHeader('Content-Type', 'text/plain');
				          
				        A function that gets a request and generates a response
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
function (Request $request, Response $response) {
  // manipulate $request to generate a $response
  return $response;
}
			

Use an additional callable during the invoke ($next)
class Middleware
{
  public function __invoke(
    \Psr\Http\Message\ServerRequestInterface $request,
    \Psr\Http\Message\ResponseInterface $response,
    callable $next = null
  ) {
    // do something before
    if ($next) {
        $next($request, $response);
    }
    // do something after
    return $response;
  }
}
				
function ($request, $response, $next)
								
								
use Zend\Expressive\AppFactory;
chdir(dirname(__DIR__));
require 'vendor/autoload.php';
$app = AppFactory::create();
$app->get('/', function ($request, $response, $next) {
  $response->getBody()->write('Hello, world!');
  return $response;
});
$app->pipeRoutingMiddleware();
$app->pipeDispatchMiddleware();
$app->run();
				
								
namespace Zend\Expressive\Router;
use Psr\Http\Message\ServerRequestInterface as Request;
interface RouterInterface
{
  public function addRoute(Route $route);
  public function match(Request $request);
  public function generateUri($name, array $substitutions = []);
}
								
// $app is an instance of Zend\Expressive\AppFactory
$app->get('/', function ($request, $response, $next) {
  $response->getBody()->write('Hello, world!');
  return $response;
});
								
// $app is an instance of Zend\Expressive\AppFactory
// Executed in all the requests
$app->pipe($apiMiddleware);
$app->pipe('middleware service name');
// Pipe to a specific URL
$app->pipe('/api', $apiMiddleware);
$app->pipe('/api', 'middleware service name');
// Error handler
$app->pipeErrorHandler('error handler service name');
$app->pipeErrorHandler('/api', 'error handler service name');
				
								
use Zend\Expressive\AppFactory;
use Zend\ServiceManager\ServiceManager;
$container = new ServiceManager();
$container->setFactory('HelloWorld', function ($container) {
  return function ($request, $response, $next) {
    $response->write('Hello, world!');
    return $response;
  };
});
$app = AppFactory::create($container);
$app->get('/', 'HelloWorld');
				We support container-interop
namespace Zend\Expressive\Template;
interface TemplateRendererInterface
{
  public function render($name, $params = []);
  public function addPath($path, $namespace = null);
  public function getPaths();
  public function addDefaultParam($templateName, $param, $value);
}
								
use Zend\Expressive\Application;
use Zend\Expressive\Plates\PlatesRenderer;
use Zend\Expressive\TemplatedErrorHandler as TErrHandler;
$plates = new PlatesRenderer();
$plates->addPath(__DIR__ . '/templates/error', 'error');
$final = new TErrHandler($plates, 'error::404', 'error::500');
$app = new Application($router, $container, $final);
								Use Vagrant to set up the environment.
Clone the repository ezimuel/zend-expressive-workshop
git clone https://github.com/ezimuel/zend-expressive-workshop
				Run composer:
cd zend-expressive-workshop
composer install
				Turn on Vagrant:
vagrant up
			The PHP server runs at localhost:8080

├── config │ └── autoload ├── data │ └── cache ├── public ├── src │ └── App │ └── Action ├── templates │ ├── app │ ├── error │ └── layout └── test
The application configuration files, including:
public/index.php (programmatic version)
$container = require 'config/container.php';
$app = $container->get(Application::class);
// Pipeline
$app->pipe(Helper\ServerUrlMiddleware::class);
// here add custom middleware ...
$app->pipeRoutingMiddleware();
$app->pipe(Helper\UrlHelperMiddleware::class);
$app->pipeDispatchMiddleware();
// Routes
$app->get('/', Action\HomePageAction::class, 'home');
$app->get('/api/ping', Action\PingAction::class, 'api.ping');
$app->run();
											src/App/Action/HomePageFactory.php
class HomePageFactory
{
  public function __invoke(ContainerInterface $container)
  {
    $router   = $container->get(RouterInterface::class);
    $template = ($container->has(TemplateRendererInterface::class))
      ? $container->get(TemplateRendererInterface::class)
      : null;
    return new HomePageAction($router, $template);
  }
}
											src/App/Action/HomePageAction.php
class HomePageAction
{
  private $router;
  private $template;
  public function __construct(
    Router\RouterInterface $router,
    Template\TemplateRendererInterface $template = null
  ){
    $this->router   = $router;
    $this->template = $template;
  }
  public function __invoke(
    ServerRequestInterface $request,
    ResponseInterface $response,
    callable $next = null
  ){
    $data = [];
    // insert value into $data
    return new HtmlResponse($this->template->render(
      'app::home-page',
      $data
    ));
  }
}
			You can check out a solution in exercise1 branch:
git checkout exercise1
				We use a Model layer to interact with the database
We built a Speaker and Talk classes in src/App/Model
You can check out a solution in exercise2 branch:
git checkout exercise2
				You can check out a solution in exercise3 branch:
	git checkout exercise3
	
				Please rate this workshop at:
https://legacy.joind.in/19407
 