рдкрддрд▓рд╛ рдорд╛рдЗрдХреНрд░реЛрдлреНрд░рд╛рдорд╡рд░реНрдХ

25 рдЕрдкреНрд░реИрд▓, 2019 рдХреЛ, рд╕реНрд▓рд┐рдо рдорд╛рдЗрдХреНрд░реЛрдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рдирдП рдкреНрд░рдореБрдЦ alpha рд╕рдВрд╕реНрдХрд░рдг рдиреЗ рджрд┐рди рдХреА рд░реЛрд╢рдиреА рджреЗрдЦреА, рдФрд░ 18 рдордИ рдХреЛ рдпрд╣ beta рдмрдврд╝ рдЧрдпрд╛ред рдореЗрд░рд╛ рд╕реБрдЭрд╛рд╡ рд╣реИ рдХрд┐ рдЖрдк рдирдП рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рдЦреБрдж рдХреЛ рдкрд░рд┐рдЪрд┐рдд рдХрд░реЗрдВред


рдХрдЯреМрддреА рдХреЗ рддрд╣рдд:


  • рдврд╛рдВрдЪреЗ рдХреЗ рдирд╡рд╛рдЪрд╛рд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ
  • рд╕реНрд▓рд┐рдо -4 рдкрд░ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдЖрд╡реЗрджрди рд▓рд┐рдЦрдирд╛
  • рд╕реНрд▓рд┐рдо рдПрдВрдб PhpStorm рджреЛрд╕реНрддреА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ

рд╕реНрд▓рд┐рдо 4 рдореЗрдВ рдирдпрд╛


рд╕рдВрд╕реНрдХрд░рдг 3 рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдкреНрд░рдореБрдЦ рдирд╡рд╛рдЪрд╛рд░:


  • PHP рдХрд╛ рдиреНрдпреВрдирддрдо рд╕рдВрд╕реНрдХрд░рдг 7.1 рд╣реИ;
  • PSR-15 (рдорд┐рдбрд▓рд╡реЗрдпрд░) рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди;
  • Http рд╕рдВрджреЗрд╢реЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ред рдХрд┐рд╕реА рднреА PSR-7 рд╕рдВрдЧрдд рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ рдФрд░ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ;
  • рдкрд┐рдореНрдкрд▓ рдирд┐рд░реНрднрд░рддрд╛ рдХреЛ рд╣рдЯрд╛ рджрд┐рдпрд╛ред рдЕрдкрдиреЗ рдкрд╕рдВрджреАрджрд╛ PSR-11 рд╕рдВрдЧрдд рдХрдВрдЯреЗрдирд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ рдФрд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ;
  • рдЖрдкрдХреЗ рд░рд╛рдЙрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ (рдкрд╣рд▓реЗ, FastRoute рдХреЛ рдЫреЛрдбрд╝рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рдерд╛);
  • рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди;
  • рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдЙрддреНрдкрд╛рджрди рдХрд╛ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди;
  • рдЖрд╡реЗрджрди рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдХрд╛рд░рдЦрд╛рдирд╛;
  • рд╣рдЯрд╛рдП рдЧрдП рд╕реЗрдЯрд┐рдВрдЧреНрд╕;
  • рд╕реНрд▓рд┐рдо рдЕрдм рдПрдХ рдЦрд╛рд▓реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкрд░ default_mimetype рд╕реЗрдЯ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ ini_set('default_mimetype', '') рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ php.ini рдпрд╛ рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдЗрд╕реЗ рд╕реНрд╡рдпрдВ рдЗрдВрд╕реНрдЯреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛;
  • рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЕрдиреБрд░реЛрдз рд╣реИрдВрдбрд▓рд░ рдЕрдм рдХреЗрд╡рд▓ рдЕрдиреБрд░реЛрдз рдСрдмреНрдЬреЗрдХреНрдЯ (рдкреБрд░рд╛рдиреЗ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ, рдпрд╣ рдЕрдиреБрд░реЛрдз рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ) рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИред

рдЕрдм рдЖрд╡реЗрджрди рдХреИрд╕реЗ рдмрдирд╛рдПрдВ?


рддреАрд╕рд░реЗ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ, рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдирд╛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╕реЗ рджреЗрдЦрд╛ рдЧрдпрд╛:


 <?php use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; use Slim\App; require 'vendor/autoload.php'; $settings = [ 'addContentLengthHeader' => false, ]; $app = new App(['settings' => $settings]); $app->get('/hello/{name}', function (ServerRequestInterface $request, ResponseInterface $response, array $args) { $name = $args['name']; $response->getBody()->write("Hello, $name"); return $response; }); $app->run(); 

рдЕрдм рдЖрд╡реЗрджрди рдирд┐рд░реНрдорд╛рддрд╛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ:


рдкреИрд░рд╛рдореАрдЯрд░рдЯрд╛рдЗрдкрдЕрдирд┐рд╡рд╛рд░реНрдпрд╡рд┐рд╡рд░рдг
$ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛Psr\Http\Message\ResponseFactoryInterfaceрд╣рд╛рдВPSR-17 рд╕рдВрдЧрдд рд╕рд░реНрд╡рд░ http рдЕрдиреБрд░реЛрдз рдХрд╛рд░рдЦрд╛рдирд╛
$ рдХрдВрдЯреЗрдирд░\Psr\Container\ContainerInterfaceрдирд╣реАрдВрдирд┐рд░реНрднрд░рддрд╛ рдХрдВрдЯреЗрдирд░
$ callableResolver\Slim\Interfaces\CallableResolverInterfaceрдирд╣реАрдВрдХреЙрд▓рдмреИрдХ рд╣реИрдВрдбрд▓рд░
$ рдорд╛рд░реНрдЧрдХреЙрд▓реЗрдХреНрдЯрд░\Slim\Interfaces\RouteCollectorInterfaceрдирд╣реАрдВрд░реВрдЯрд░
$ рдорд╛рд░реНрдЧ\Slim\Interfaces\RouteResolverInterfaceрдирд╣реАрдВрд░реВрдЯрд┐рдВрдЧ рдкрд░рд┐рдгрд╛рдо рд╣реИрдВрдбрд▓рд░

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдЕрдм рдЖрдк рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдлрд╝реИрдХреНрдЯрд░реА \Slim\Factory\AppFactory рдХреЗ рд╕реНрдерд┐рд░ create рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдпрд╣ рд╡рд┐рдзрд┐ рдЗрдирдкреБрдЯ рдХреЗ рд╕рдорд╛рди рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреА рд╣реИ, рдХреЗрд╡рд▓ рд╡реЗ рд╕рднреА рд╡реИрдХрд▓реНрдкрд┐рдХ рд╣реИрдВред


 <?php use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; use Slim\Factory\AppFactory; require 'vendor/autoload.php'; $app = AppFactory::create(); $app->get('/hello/{name}', function (ServerRequestInterface $request, ResponseInterface $response) { $name = $request->getAttribute('name'); $response->getBody()->write("Hello, $name"); return $response; }); $app->run(); 

рдореБрдЭреЗ 404 рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╡рд╛рдкрд╕ рджреЗрдВ!


рдпрджрд┐ рд╣рдо рдПрдХ рдЧреИрд░-рдореМрдЬреВрдж рдкреГрд╖реНрда рдЦреЛрд▓рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ 500 рдХрд╛ рдПрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЛрдб рдорд┐рд▓рддрд╛ рд╣реИ, рди рдХрд┐ 404 ред рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ \Slim\Middleware\ErrorMiddleware рдХрдиреЗрдХреНрдЯ \Slim\Middleware\ErrorMiddleware


 <?php use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; use Slim\Factory\AppFactory; use Slim\Middleware\ErrorMiddleware; require 'vendor/autoload.php'; $app = AppFactory::create(); $middleware = new ErrorMiddleware( $app->getCallableResolver(), $app->getResponseFactory(), false, false, false ); $app->add($middleware); $app->get('/hello/{name}', function (ServerRequestInterface $request, ResponseInterface $response) { $name = $request->getAttribute('name'); $response->getBody()->write("Hello, $name"); return $response; }); $app->run(); 

middleware


рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЛ рдЕрдм PSR-15 рд▓рд╛рдЧреВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЕрдкрд╡рд╛рдж рдХреЗ рд░реВрдк рдореЗрдВ, рдЖрдк рдлрд╝рдВрдХреНрд╢рдВрд╕ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХреЛ process() \Psr\Http\Server\MiddlewareInterface рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреА рд╡рд┐рдзрд┐ рд╕реЗ рдореЗрд▓ рдЦрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП


 <?php use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Server\RequestHandlerInterface; use Slim\Factory\AppFactory; require 'vendor/autoload.php'; $app = AppFactory::create(); $app->add(function (ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $response = $handler->handle($request); return $response->withHeader('Content-Type', 'application/json'); }); // ...     $app->run(); 

рд╣рд╕реНрддрд╛рдХреНрд╖рд░ ($request, $response, $next) рдЕрдм рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рд╣реИ


рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЗ рдмрд┐рдирд╛ рдХреИрд╕реЗ рд░рд╣реЗрдВ?


рдЖрдк рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЗ рдмрд┐рдирд╛ рд░рд╣ рд╕рдХрддреЗ рд╣реИрдВред рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП рдЙрдкрдХрд░рдг рд╣рдореЗрдВ рдЗрд╕рдореЗрдВ рдорджрдж рдХрд░реЗрдВрдЧреЗред


httpVersion рдФрд░ responseChunkSize


рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рд▓рд┐рдП httpVersion рд╕реЗрдЯрд┐рдВрдЧ рдЬрд┐рдореНрдореЗрджрд╛рд░ рдереАред
рдЬрдм рдХрд┐рд╕реА рдмреНрд░рд╛рдЙрдЬрд░ рдХреЛ рднреЗрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИ рддреЛ рд░рд┐рд╕реНрдкрд╛рдВрд╕ рдмреЙрдбреА рд╕реЗ рдкрдврд╝реЗ рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдкреНрд░рддреНрдпреЗрдХ рдЪрдВрдХ рдХрд╛ рд╕рд╛рдЗрдЬ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИред


рдЕрдм рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЙрддреНрддрд░ рдХреЗ рдПрдорд┐рдЯрд░ рдХреЛ рд╕реМрдВрдкрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред


рдЗрдорд░рддреА рд▓рд┐рдЦрд┐рдП


 <?php // /src/ResponseEmitter.php namespace App; use Psr\Http\Message\ResponseInterface; use Slim\ResponseEmitter as SlimResponseEmitter; class ResponseEmitter extends SlimResponseEmitter { private $protocolVersion; public function __construct(string $protocolVersion = '1.1', int $responseChunkSize = 4096) { $this->protocolVersion = $protocolVersion; parent::__construct($responseChunkSize); } public function emit(ResponseInterface $response) : void{ parent::emit($response->withProtocolVersion($this->protocolVersion)); } } 

рд╣рдо рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рддреЗ рд╣реИрдВ


 <?php use App\ResponseEmitter; use Slim\Factory\AppFactory; require 'vendor/autoload.php'; $app = AppFactory::create(); $serverRequestFactory = \Slim\Factory\ServerRequestCreatorFactory::create(); $request = $serverRequestFactory->createServerRequestFromGlobals(); // ...     $response = $app->handle($request); $emitter = new ResponseEmitter('2.0', 4096); $emitter->emit($response); 

outputBuffering


рдЗрд╕ рд╕реЗрдЯрд┐рдВрдЧ рдиреЗ рдЖрдЙрдЯрдкреБрдЯ рдмрдлрд░рд┐рдВрдЧ рдХреЛ рдЪрд╛рд▓реВ / рдмрдВрдж рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреАред рдорд╛рди рд╕реЗрдЯ рдХрд░рдирд╛:


  • false - рдмрдлрд░рд┐рдВрдЧ рдмрдВрдж рдХрд░ рджреА рдЧрдИ рд╣реИ (рд╕рднреА рдХреЙрд▓ echo рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, print рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдХреЛ рдирдЬрд░рдЕрдВрджрд╛рдЬ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ)
  • 'append' - рд╕рднреА рдХреЙрд▓ echo , print рд╕реНрдЯреЗрдЯрдореЗрдВрдЯреНрд╕ рдХреЛ рд░рд┐рд╕реНрдкреЙрдиреНрд╕ рдмреЙрдбреА рдХреЗ рдмрд╛рдж рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ
  • 'prepend' - рд╕рднреА рдХреЙрд▓ echo , print рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдХреЛ рд░рд┐рд╕реНрдкреЙрдиреНрд╕ рдмреЙрдбреА рд╕реЗ рдкрд╣рд▓реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ

\Slim\Middleware\OutputBufferingMiddleware рдбреЗрд╡рд▓рдкрд░реНрд╕ рдиреЗ рдЗрд╕ рд╡рд┐рдХрд▓реНрдк рдХреЛ \Slim\Middleware\OutputBufferingMiddleware рдХреЗ рдирд┐рд░реНрдорд╛рдг рдореЗрдВ рдмрджрд▓рдиреЗ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ \Slim\Middleware\OutputBufferingMiddleware , рдЬрд┐рд╕рдореЗрдВ рдПрдХ PSR-17 рд╕рдВрдЧрдд рд╕реНрдЯреНрд░реАрдо рдлреИрдХреНрдЯрд░реА рдФрд░ рдПрдХ рдореЛрдб рдЬреЛ append рдпрд╛ prepend рдмрд░рд╛рдмрд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, prepend


 <?php use Slim\Factory\AppFactory; use Slim\Factory\Psr17\SlimPsr17Factory; use Slim\Middleware\OutputBufferingMiddleware; require 'vendor/autoload.php'; $app = AppFactory::create(); $middleware = new OutputBufferingMiddleware(SlimPsr17Factory::getStreamFactory(), OutputBufferingMiddleware::APPEND); $app->add($middleware); // ...     $app->run(); 

determineRouteBeforeAppMiddleware


рдЗрд╕ рд╕реЗрдЯрд┐рдВрдЧ рдиреЗ рдорд┐рдбрд┐рд▓рд╡реЗрдпрд░ рдореЗрдВ рдЕрдиреБрд░реЛрдз рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реЗ рд╡рд░реНрддрдорд╛рди рдорд╛рд░реНрдЧ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╕рдВрднрд╡ рдмрдирд╛ рджрд┐рдпрд╛


рдПрдХ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ \Slim\Middleware\RoutingMiddleware


 <?php use Slim\Factory\AppFactory; use Slim\Middleware\RoutingMiddleware; require 'vendor/autoload.php'; $app = AppFactory::create(); $middleware = new RoutingMiddleware($app->getRouteResolver()); $app->add($middleware); // ...     $app->run(); 

displayErrorDetails


рд╕реЗрдЯрд┐рдВрдЧ рдореЗрдВ рддреНрд░реБрдЯрд┐ рд╡рд┐рд╡рд░рдг рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рд╣реИред рдбрд┐рдмрдЧрд┐рдВрдЧ рдХрд░рддреЗ рд╕рдордп, рдпрд╣ рдЬреАрд╡рди рдХреЛ рдЖрд╕рд╛рди рдмрдирд╛рддрд╛ рд╣реИред


рдпрд╛рдж рд░рдЦреЗрдВ \Slim\Middleware\ErrorMiddleware ? рдпрд╣рд╛рдБ рдпрд╣ рд╣рдорд╛рд░реА рдорджрдж рдХрд░реЗрдЧрд╛!


 <?php use Slim\Factory\AppFactory; use Slim\Middleware\ErrorMiddleware; require 'vendor/autoload.php'; $app = AppFactory::create(); $middleware = new ErrorMiddleware( $app->getCallableResolver(), $app->getResponseFactory(), true, //        false, //   false //    ); $app->add($middleware); // ...     $app->run(); 

addContentLengthHeader


рдЗрд╕ рд╕реЗрдЯрд┐рдВрдЧ рдиреЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдмреЙрдбреА рдореЗрдВ рдбреЗрдЯрд╛ рд╡реЙрд▓реНрдпреВрдо рдХреЗ рдореВрд▓реНрдп рдХреЗ рд╕рд╛рде Content-Length рд╣реЗрдбрд░ рдХреЗ рдСрдЯреЛ-рдПрдбрд┐рд╢рди рдХреЛ рд╕рдХреНрд╖рдо / рдЕрдХреНрд╖рдо рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреА


рдорд┐рдбрд▓рд╡реЗрдпрд░ рд╡рд┐рдХрд▓реНрдк \Slim\Middleware\ContentLengthMiddleware


 <?php use Slim\Factory\AppFactory; use Slim\Middleware\ContentLengthMiddleware; require 'vendor/autoload.php'; $app = AppFactory::create(); $middleware = new ContentLengthMiddleware(); $app->add($middleware); // ...     $app->run(); 

routerCacheFile


рдЕрдм рдЖрдк рд╕реАрдзреЗ рд░рд╛рдЙрдЯрд░ рдХреИрд╢ рдлрд╝рд╛рдЗрд▓ рд╕реНрдерд╛рдкрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ


 <?php use Slim\Factory\AppFactory; require 'vendor/autoload.php'; $app = AppFactory::create(); $app->getRouteCollector()->setCacheFile('/path/to/cache/router.php'); // ...     $app->run(); 

рд╕реНрд▓рд┐рдо -4 рдкрд░ рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдирд╛


рд░реВрдкрд░реЗрдЦрд╛ рдкрд░ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рдЖрд╡реЗрджрди рд▓рд┐рдЦреЗрдВрдЧреЗред


рдЖрд╡реЗрджрди рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдорд╛рд░реНрдЧ рд╣реЛрдВрдЧреЗ:


  • /hello/{name} - рд╕реНрд╡рд╛рдЧрдд рдкреГрд╖реНрда;
  • / - рдкреГрд╖реНрда /hello/world рд▓рд┐рдП рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд
  • рдЕрдиреНрдп рдорд╛рд░реНрдЧ 404 рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдХрд╕реНрдЯрдо рдкреГрд╖реНрда рд▓реМрдЯрд╛рдПрдВрдЧреЗред

рдирд┐рдпрдВрддреНрд░рдХ рдореЗрдВ рддрд░реНрдХ рд╣реЛрдЧрд╛, рд╣рдо рдкреГрд╖реНрда рдХреЛ рдЯреНрд╡реАрдЧ рдЯреЗрдореНрдкрд▓реЗрдЯ рдЗрдВрдЬрди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рд╕реНрддреБрдд рдХрд░реЗрдВрдЧреЗ
рдПрдХ рдмреЛрдирд╕ рдХреЗ рд░реВрдк рдореЗрдВ, рдорд╛рд░реНрдЧреЛрдВ рдХреА рд╕реВрдЪреА рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реА рдХрдорд╛рдВрдб рдХреЗ рд╕рд╛рде рд╕рд┐рдореНрдлрдиреА рдХрдВрд╕реЛрд▓ рдШрдЯрдХ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рдХрдВрд╕реЛрд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЬреЛрдбрд╝реЗрдВ


рдЪрд░рдг 0. рдирд┐рд░реНрднрд░рддрд╛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛


рд╣рдореЗрдВ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:



рдореИрдВрдиреЗ рдЕрд▓реНрдЯреНрд░рд╛-рд▓рд╛рдЗрдЯ / рдХрдВрдЯреЗрдирд░ рдХреЛ рдирд┐рд░реНрднрд░рддрд╛ рдХрдВрдЯреЗрдирд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЪреБрдирд╛ , рд╣рд▓реНрдХреЗ, рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдФрд░ рдорд╛рдирдХ рдХреЗ рдЕрдиреБрд░реВрдкред
PSR-7 рдФрд░ PSR-17 рд╕реНрд▓рд┐рдо рдбреЗрд╡рд▓рдкрд░реНрд╕ рдПрдХ рдкреИрдХреЗрдЬ рдореЗрдВ рд╕реНрд▓рд┐рдо / ps7 рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ


рдпрд╣ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рд╕рдВрдЧреАрддрдХрд╛рд░ рдкреИрдХреЗрдЬ рдкреНрд░рдмрдВрдзрдХ рдкрд╣рд▓реЗ рд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рд╣реИред

рд╣рдо рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╝реЛрд▓реНрдбрд░ рдмрдирд╛рддреЗ рд╣реИрдВ ( /path/to/project рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛) рдФрд░ рдЙрд╕ рдкрд░ рдЬрд╛рдПрдВред


рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╕рд╛рде рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ composer.json рдлрд╝рд╛рдЗрд▓ рдЬреЛрдбрд╝реЗрдВ:


 { "require": { "php": ">=7.1", "slim/slim": "4.0.0-beta", "slim/psr7": "~0.3", "ultra-lite/container": "^6.2", "symfony/console": "^4.2", "twig/twig": "^2.10" }, "autoload": { "psr-4": { "App\\": "app" } } } 

рдФрд░ рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ


 composer install 

рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдкреИрдХреЗрдЬ рд╣реИрдВ рдФрд░ рдХреНрд▓рд╛рд╕ рдСрдЯреЛрд▓реИрдбрд░ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред


рдпрджрд┐ рд╣рдо git рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рддреЛ .gitignore рдлрд╝рд╛рдЗрд▓ рдЬреЛрдбрд╝реЗрдВ рдФрд░ рд╡рд╣рд╛рдВ vendor рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдЬреЛрдбрд╝реЗрдВ (рдФрд░ рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рддреЛ рдЖрдкрдХреЗ IDE рдХреА рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА)


 /.idea/* /vendor/* 

рдореИрдВ PhpStorm IDE рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдЗрд╕ рдкрд░ рдЧрд░реНрд╡ рд╣реИ ред рдПрдХ рдЖрд░рд╛рдорджрд╛рдпрдХ рд╡рд┐рдХрд╛рд╕ рдХреЗ рд▓рд┐рдП, рдХрдВрдЯреЗрдирд░ рдФрд░ рдЖрдИрдбреАрдИ рдХреЗ рд╕рд╛рде рджреЛрд╕реНрддреА рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред
рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреА рдЬрдбрд╝ рдореЗрдВ, .phpstorm.meta.php рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБ рдФрд░ рд╡рд╣рд╛рдБ рдирд┐рдореНрди рдХреЛрдб рд▓рд┐рдЦреЗрдВ:


 <?php // .phpstorm.meta.php namespace PHPSTORM_META { override( \Psr\Container\ContainerInterface::get(0), map([ '' => '@', ]) ); } 

рдпрд╣ рдХреЛрдб рдЖрдИрдбреАрдИ рдХреЛ рдмрддрд╛рдПрдЧрд╛ рдХрд┐ рдЬрд┐рд╕ рд╡рд╕реНрддреБ рдХреЗ рд▓рд┐рдП \Psr\Container\ContainerInterface рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, get() рд╡рд┐рдзрд┐ рдПрдХ рдХреНрд▓рд╛рд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдпрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓реМрдЯрд╛ рджреЗрдЧреА рдЬрд┐рд╕рдХрд╛ рдирд╛рдо рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред


рдЪрд░рдг 1. рдЖрд╡реЗрджрди рдлреНрд░реЗрдорд╡рд░реНрдХ


рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдПрдВ рдЬреЛрдбрд╝реЗрдВ:


  • app - рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛрдбред рд╣рдо рд╡рд░реНрдЧ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рдирд╛рдорд╕реНрдерд╛рди рдХреЛ рдЗрд╕рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд░реЗрдВрдЧреЗ;
  • bin - рдХрдВрд╕реЛрд▓ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛;
  • config - рдпрд╣рд╛рдВ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╛рдЗрд▓реЗрдВ рд╣реЛрдВрдЧреА;
  • public - рд╡реЗрдм рдкрд░ рдПрдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдЦреЛрд▓реА рдЧрдИ (рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдмрд┐рдВрджреБ, рд╢реИрд▓рд┐рдпреЛрдВ, рдЬреЗрдПрд╕, рдЪрд┐рддреНрд░, рдЖрджрд┐);
  • template - template рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛;
  • var рд╡рд┐рднрд┐рдиреНрди рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рд╣реИред рд▓реЙрдЧреНрд╕, рдХреИрд╢, рд▓реЛрдХрд▓ рд╕реНрдЯреЛрд░реЗрдЬ рдЗрддреНрдпрд╛рджрд┐ред

рдФрд░ рдлрд╛рдЗрд▓реЗрдВ:


  • config/app.ini - рдореБрдЦреНрдп рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди;
  • config/app.local.ini - local рдкрд░реНрдпрд╛рд╡рд░рдг рдХреЗ рд▓рд┐рдП рд╡рд┐рдиреНрдпрд╛рд╕;
  • app/Support/CommandMap.php - рдЖрд▓рд╕реА рд▓реЛрдбрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдХрдВрд╕реЛрд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрдорд╛рдВрдб рдХреА рдореИрдкрд┐рдВрдЧред
  • app/Support/Config.php - рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╡рд░реНрдЧ (рддрд╛рдХрд┐ рдЖрдИрдбреАрдИ рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреМрди рд╕рд╛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╣реИ)ред
  • app/Support/NotFoundHandler.php - 404 рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд░ рд╡рд░реНрдЧред
  • app/Support/ServiceProviderInterface.php - рд╕реЗрд╡рд╛ рдкреНрд░рджрд╛рддрд╛ рдХрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ред
  • app/Provider/AppProvider.php - рдЖрд╡реЗрджрди рдХрд╛ рдореБрдЦреНрдп рдкреНрд░рджрд╛рддрд╛ред
  • bootstrap.php - рдХрдВрдЯреЗрдирд░ рдЕрд╕реЗрдВрдмрд▓реА;
  • bin/console - рдХрдВрд╕реЛрд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБ;
  • public/index.php - рд╡реЗрдм рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХрд╛ рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБред

config / app.ini
 ;   slim.debug=Off ;   templates.dir=template ;   templates.cache=var/cache/template 

config / app.local.ini
 ;        .       ;        slim.debug=On ;       templates.cache= 

рдЕрд░реЗ рд╣рд╛рдБ, рдпрд╣ рдЕрднреА рднреА рдкрд░реНрдпрд╛рд╡рд░рдг рдХреЛ рдмрд╛рд╣рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫрд╛ рд╣реИ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рддрд╛ рд╣реИред рдЖрдЦрд┐рд░рдХрд╛рд░, рд╡рд╣рд╛рдБ рджрд┐рдЦрд╛рд╡реЗ / рдкрд╛рд╕рд╡рд░реНрдб рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдХреИрд╢ рднреА рдмрд╛рд╣рд░ рд░рдЦрд╛ рдЧрдпрд╛ рд╣реИред


.gitignore
 /.idea/* /config/* /vendor/* /var/cache/* !/config/app.ini !/var/cache/.gitkeep 

рдПрдкреНрд▓рд┐рдХреЗрд╢рди / рд╕рдорд░реНрдерди / CommandMap.php
 <?php // app/Support/CommandMap.php namespace App\Support; class CommandMap { /** *  .   =>    * @var string[] */ private $map = []; public function set(string $name, string $value) { $this->map[$name] = $value; } /** * @return string[] */ public function getMap() { return $this->map; } } 

рдПрдкреНрд▓рд┐рдХреЗрд╢рди / рд╕рдорд░реНрдерди / config.php
 <?php // app/Support/Config.php namespace App\Support; class Config { /** * @var string[] */ private $config = []; public function __construct(string $dir, string $env, string $root) { if (!is_dir($dir)) return; /* *    */ $config = (array)parse_ini_file($dir . DIRECTORY_SEPARATOR . 'app.ini', false); /* *      */ $environmentConfigFile = $dir . DIRECTORY_SEPARATOR . 'app.' . $env . '.ini'; if (is_readable($environmentConfigFile)) { $config = array_replace_recursive($config, (array)parse_ini_file($environmentConfigFile, false)); } /* * ,      */ $dirs = ['templates.dir', 'templates.cache']; foreach ($config as $name=>$value) { $this->config[$name] = $value; } /* *      */ foreach ($dirs as $parameter) { $value = $config[$parameter]; if (mb_strpos($value, '/') === 0) { continue; } if (empty($value)) { $this->config[$parameter] = null; continue; } $this->config[$parameter] = $root . DIRECTORY_SEPARATOR . $value; } } public function get(string $name) { return array_key_exists($name, $this->config) ? $this->config[$name] : null; } } 

рдПрдкреНрд▓рд┐рдХреЗрд╢рди / рд╕рдорд░реНрдерди / NotFoundHandler.php
 <?php // app/Support/NotFoundHandler.php namespace App\Support; use Psr\Http\Message\ResponseFactoryInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Slim\Interfaces\ErrorHandlerInterface; use Throwable; class NotFoundHandler implements ErrorHandlerInterface { private $factory; public function __construct(ResponseFactoryInterface $factory) { $this->factory = $factory; } /** * @param ServerRequestInterface $request * @param Throwable $exception * @param bool $displayErrorDetails * @param bool $logErrors * @param bool $logErrorDetails * @return ResponseInterface */ public function __invoke(ServerRequestInterface $request, Throwable $exception, bool $displayErrorDetails, bool $logErrors, bool $logErrorDetails): ResponseInterface { $response = $this->factory->createResponse(404); return $response; } } 

рдЕрдм рдЖрдк PhpStorm рдХреЛ рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд┐рдЦрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХрд┐рд╕ рдХреБрдВрдЬреА рдореЗрдВ рдХреБрдВрдЬреА рд╣реИ рдФрд░ рд╡реЗ рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рд╣реИрдВ


.phpstorm.meta.php
 <?php // .phpstorm.meta.php namespace PHPSTORM_META { override( \Psr\Container\ContainerInterface::get(0), map([ '' => '@', ]) ); override( \App\Support\Config::get(0), map([ 'slim.debug' => 'bool', 'templates.dir' => 'string|false', 'templates.cache' => 'string|false', ]) ); } 

рдПрдкреНрд▓рд┐рдХреЗрд╢рди / рд╕рдорд░реНрдерди / ServiceProviderInterface.php
 <?php // app/Support/ServiceProviderInterface.php namespace App\Support; use UltraLite\Container\Container; interface ServiceProviderInterface { public function register(Container $container); } 

рдПрдкреНрд▓рд┐рдХреЗрд╢рди / рдкреНрд░рджрд╛рддрд╛ / AppProvider.php
 <?php // app/Provider/AppProvider.php namespace App\Provider; use App\Support\CommandMap; use App\Support\Config; use App\Support\NotFoundHandler; use App\Support\ServiceProviderInterface; use Psr\Container\ContainerInterface; use Psr\Http\Message\ResponseFactoryInterface; use Slim\CallableResolver; use Slim\Exception\HttpNotFoundException; use Slim\Interfaces\CallableResolverInterface; use Slim\Interfaces\RouteCollectorInterface; use Slim\Interfaces\RouteResolverInterface; use Slim\Middleware\ErrorMiddleware; use Slim\Middleware\RoutingMiddleware; use Slim\Psr7\Factory\ResponseFactory; use Slim\Routing\RouteCollector; use Slim\Routing\RouteResolver; use UltraLite\Container\Container; class AppProvider implements ServiceProviderInterface { public function register(Container $container) { /* *     */ $container->set(CommandMap::class, function () { return new CommandMap(); }); /* *   http- */ $container->set(ResponseFactory::class, function () { return new ResponseFactory(); }); /* *    http-   */ $container->set(ResponseFactoryInterface::class, function (ContainerInterface $container) { return $container->get(ResponseFactory::class); }); /* *     */ $container->set(CallableResolver::class, function (ContainerInterface $container) { return new CallableResolver($container); }); /* *        */ $container->set(CallableResolverInterface::class, function (ContainerInterface $container) { return $container->get(CallableResolver::class); }); /* *   */ $container->set(RouteCollector::class, function (ContainerInterface $container) { $router = new RouteCollector( $container->get(ResponseFactoryInterface::class), $container->get(CallableResolverInterface::class), $container ); return $router; }); /* *      */ $container->set(RouteCollectorInterface::class, function (ContainerInterface $container) { return $container->get(RouteCollector::class); }); /* *     */ $container->set(RouteResolver::class, function (ContainerInterface $container) { return new RouteResolver($container->get(RouteCollectorInterface::class)); }); /* *        */ $container->set(RouteResolverInterface::class, function (ContainerInterface $container) { return $container->get(RouteResolver::class); }); /* *    404 */ $container->set(NotFoundHandler::class, function (ContainerInterface $container) { return new NotFoundHandler($container->get(ResponseFactoryInterface::class)); }); /* *  middleware   */ $container->set(ErrorMiddleware::class, function (ContainerInterface $container) { $middleware = new ErrorMiddleware( $container->get(CallableResolverInterface::class), $container->get(ResponseFactoryInterface::class), $container->get(Config::class)->get('slim.debug'), true, true); $middleware->setErrorHandler(HttpNotFoundException::class, $container->get(NotFoundHandler::class)); return $middleware; }); /* *  middleware  */ $container->set(RoutingMiddleware::class, function (ContainerInterface $container) { return new RoutingMiddleware($container->get(RouteResolverInterface::class)); }); } } 

рд╣рдордиреЗ рдХрдВрдЯреЗрдирд░ рдореЗрдВ рд░реВрдЯрд┐рдВрдЧ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рджрд┐рдпрд╛, рддрд╛рдХрд┐ рд╣рдо рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд╕рдХреЗрдВ рдФрд░ рдмрд┐рдирд╛ рдХрд┐рд╕реА \Slim\App рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдкреНрд░рд╛рд░рдВрдн рдХрд┐рдП рдмрд┐рдирд╛ред


bootstrap.php
 <?php // bootstrap.php require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; use App\Support\ServiceProviderInterface; use App\Provider\AppProvider; use App\Support\Config; use UltraLite\Container\Container; /* *   */ $env = getenv('APP_ENV'); if (!$env) $env = 'local'; /* *   */ $config = new Config(__DIR__ . DIRECTORY_SEPARATOR . 'config', $env, __DIR__); /* *  - */ $providers = [ AppProvider::class, ]; /* *    */ $container = new Container([ Config::class => function () use ($config) { return $config;}, ]); /* *   */ foreach ($providers as $className) { if (!class_exists($className)) { /** @noinspection PhpUnhandledExceptionInspection */ throw new Exception('Provider ' . $className . ' not found'); } $provider = new $className; if (!$provider instanceof ServiceProviderInterface) { /** @noinspection PhpUnhandledExceptionInspection */ throw new Exception($className . ' has not provider'); } $provider->register($container); } /* *   */ return $container; 

рдмрд┐рди / рд╕рд╛рдВрддреНрд╡рдирд╛
 #!/usr/bin/env php <?php // bin/console use App\Support\CommandMap; use Psr\Container\ContainerInterface; use Symfony\Component\Console\Application; use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Output\ConsoleOutput; /** @var ContainerInterface $container */ $container = require dirname(__DIR__) . DIRECTORY_SEPARATOR . 'bootstrap.php'; $loader = new ContainerCommandLoader($container, $container->get(CommandMap::class)->getMap()); $app = new Application(); $app->setCommandLoader($loader); /** @noinspection PhpUnhandledExceptionInspection */ $app->run(new ArgvInput(), new ConsoleOutput()); 

рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдирд╛ рдЙрдЪрд┐рдд рд╣реИ


 chmod +x ./bin/console 

public / index.php
 <?php // public/index.php use Psr\Container\ContainerInterface; use Psr\Http\Message\ResponseFactoryInterface; use Slim\App; use Slim\Interfaces\CallableResolverInterface; use Slim\Interfaces\RouteCollectorInterface; use Slim\Interfaces\RouteResolverInterface; use Slim\Middleware\ErrorMiddleware; use Slim\Middleware\RoutingMiddleware; use Slim\Psr7\Factory\ServerRequestFactory; /** @var ContainerInterface $container */ $container = require dirname(__DIR__) . DIRECTORY_SEPARATOR . 'bootstrap.php'; $request = ServerRequestFactory::createFromGlobals(); Slim\Factory\AppFactory::create(); $app = new App( $container->get(ResponseFactoryInterface::class), $container, $container->get(CallableResolverInterface::class), $container->get(RouteCollectorInterface::class), $container->get(RouteResolverInterface::class) ); $app->add($container->get(RoutingMiddleware::class)); $app->add($container->get(ErrorMiddleware::class)); $app->run($request); 

рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВред
рдХрдВрд╕реЛрд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓реЙрдиреНрдЪ рдХрд░реЗрдВ:


 ./bin/console 

рдЬрд╡рд╛рдм рдореЗрдВ, symfony/console рдШрдЯрдХ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рд╛рдЧрдд рд╡рд┐рдВрдбреЛ рджреЛ рдЙрдкрд▓рдмреНрдз рдХрдорд╛рдВрдб - help рдФрд░ list рд╕рд╛рде рджрд┐рдЦрд╛рдИ рджреЗрдиреА рдЪрд╛рд╣рд┐рдПред


 Console Tool Usage: command [options] [arguments] Options: -h, --help Display this help message -q, --quiet Do not output any message -V, --version Display this application version --ansi Force ANSI output --no-ansi Disable ANSI output -n, --no-interaction Do not ask any interactive question -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug Available commands: help Displays help for a command list Lists commands 

рдЕрдм рд╡реЗрдм рд╕рд░реНрд╡рд░ рд╢реБрд░реВ рдХрд░реЗрдВред


 php -S localhost:8080 -t public public/index.php 

рдФрд░ рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ рдкрд░ рдХреЛрдИ рднреА рдпреВрдЖрд░рдПрд▓ рдЦреЛрд▓реЗрдВ: 8080ред
рд╕рднреА рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдХреЛрдб 404 рдФрд░ рдПрдХ рдЦрд╛рд▓реА рдирд┐рдХрд╛рдп рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╡рд╛рдкрд╕ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдПред
рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реЛрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреЛрдИ рд░реВрдЯ рд╕реВрдЪреАрдмрджреНрдз рдирд╣реАрдВ рд╣реИред


рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рд░реЗрдВрдбрд░ рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ, рдЯреЗрдореНрдкреНрд▓реЗрдЯ, рдХрдВрдЯреНрд░реЛрд▓рд░ рдФрд░ рд╕реЗрдЯ рд░реВрдЯ рд▓рд┐рдЦрдиреЗ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИред


рдЪрд░рдг 2. рд░реЗрдВрдбрд░


рдЯреЗрдореНрдкрд▓реЗрдЯ template/layout.twig рдЬреЛрдбрд╝реЗрдВ template/layout.twig ред рдпрд╣ рд╕рднреА рдкреГрд╖реНрдареЛрдВ рдХреЗ рд▓рд┐рдП рдореВрд▓ рдЯреЗрдореНрдкрд▓реЗрдЯ рд╣реИред


рдЯреЗрдореНрдкрд▓реЗрдЯ / рд▓реЗрдЖрдЙрдЯ
 {# template/layout.twig #} <!DOCTYPE html> <html lang="en"> <head> <title>{% block title %}Slim demo{% endblock %}</title> </head> <body> {% block content %}{% endblock %} </body> </html> 

рдПрдХ рд╕реНрд╡рд╛рдЧрдд рдкреГрд╖реНрда template/hello.twig рдЬреЛрдбрд╝реЗрдВ template/hello.twig


рдЯреЗрдореНрдкрд▓реЗрдЯ / hello.twig
 {# template/hello.twig #} {% extends 'layout.twig' %} {% block title %}Slim demo::hello, {{ name }}{% endblock %} {% block content %} <h1>Welcome!</h1> <p>Hello, {{ name }}!</p> {% endblock %} 

рдФрд░ рдПрд░рд░ рдкреЗрдЬ template/err404.twig


рдЯреЗрдореНрдкреНрд▓реЗрдЯ / рдЧрд╝рд▓рддреА рд╕реЗ ред404
 {# template/err404.twig #} {% extends 'layout.twig' %} {% block title %}Slim demo::not found{% endblock %} {% block content %} <h1>Error!</h1> <p>Page not found =(</p> {% endblock %} 

рд░реЗрдВрдбрд░рд┐рдВрдЧ рдкреНрд░рджрд╛рддрд╛ app/Provider/RenderProvider.php


рдПрдкреНрд▓рд┐рдХреЗрд╢рди / рдкреНрд░рджрд╛рддрд╛ / RenderProvider.php
 <?php // app/Provider/RenderProvider.php namespace App\Provider; use App\Support\Config; use App\Support\ServiceProviderInterface; use Psr\Container\ContainerInterface; use Twig\Environment; use Twig\Loader\FilesystemLoader; use UltraLite\Container\Container; class RenderProvider implements ServiceProviderInterface { public function register(Container $container) { $container->set(Environment::class, function (ContainerInterface $container) { $config = $container->get(Config::class); $loader = new FilesystemLoader($config->get('templates.dir')); $cache = $config->get('templates.cache'); $options = [ 'cache' => empty($cache) ? false : $cache, ]; $twig = new Environment($loader, $options); return $twig; }); } } 

рдкреНрд░рджрд╛рддрд╛ рдХреЛ рдмреВрдЯрд╕реНрдЯреНрд░реИрдк рдореЗрдВ рдЪрд╛рд▓реВ рдХрд░реЗрдВ


bootstrap.php
 <?php // bootstrap.php // ... use App\Provider\RenderProvider; // ... $providers = [ // ... RenderProvider::class, // ... ]; // ... 

404 рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд░ рдореЗрдВ рд░реЗрдВрдбрд░ рдЬреЛрдбрд╝реЗрдВ


рдПрдкреНрд▓рд┐рдХреЗрд╢рди / рд╕рдорд░реНрдерди / NotFoundHandler.php (DIFF)
 --- a/app/Support/NotFoundHandler.php +++ b/app/Support/NotFoundHandler.php @@ -8,15 +8,22 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Slim\Interfaces\ErrorHandlerInterface; use Throwable; +use Twig\Environment; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; +use Twig\Error\SyntaxError; class NotFoundHandler implements ErrorHandlerInterface { private $factory; - public function __construct(ResponseFactoryInterface $factory) + private $render; + + public function __construct(ResponseFactoryInterface $factory, Environment $render) { $this->factory = $factory; + $this->render = $render; } /** @@ -26,10 +33,14 @@ class NotFoundHandler implements ErrorHandlerInterface * @param bool $logErrors * @param bool $logErrorDetails * @return ResponseInterface + * @throws LoaderError + * @throws RuntimeError + * @throws SyntaxError */ public function __invoke(ServerRequestInterface $request, Throwable $exception, bool $displayErrorDetails, bool $logErrors, bool $logErrorDetails): ResponseInterface { $response = $this->factory->createResponse(404); + $response->getBody()->write($this->render->render('err404.twig')); return $response; } } 

рдПрдкреНрд▓рд┐рдХреЗрд╢рди / рдкреНрд░рджрд╛рддрд╛ / AppProvider.php (DIFF)
 --- a/app/Provider/AppProvider.php +++ b/app/Provider/AppProvider.php @@ -19,6 +19,7 @@ use Slim\Middleware\RoutingMiddleware; use Slim\Psr7\Factory\ResponseFactory; use Slim\Routing\RouteCollector; use Slim\Routing\RouteResolver; +use Twig\Environment; use UltraLite\Container\Container; class AppProvider implements ServiceProviderInterface @@ -99,7 +100,7 @@ class AppProvider implements ServiceProviderInterface *    404 */ $container->set(NotFoundHandler::class, function (ContainerInterface $container) { - return new NotFoundHandler($container->get(ResponseFactoryInterface::class)); + return new NotFoundHandler($container->get(ResponseFactoryInterface::class), $container->get(Environment::class)); }); /* 

404 .


3.



2:


  • app/Controller/HomeController.php тАФ
  • app/Controller/HelloController.php тАФ

( URL ), тАФ ( html)


app/Controller/HomeController.php
 <?php // app/Controller/HomeController.php namespace App\Controller; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Slim\Interfaces\RouteParserInterface; class HomeController { /** * @var RouteParserInterface */ private $router; public function __construct(RouteParserInterface $router) { $this->router = $router; } public function index(ServerRequestInterface $request, ResponseInterface $response) { $uri = $this->router->fullUrlFor($request->getUri(), 'hello', ['name' => 'world']); return $response ->withStatus(301) ->withHeader('location', $uri); } } 

app/Controller/HelloController.php
 <?php // app/Controller/HelloController.php namespace App\Controller; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Twig\Environment as Render; use Twig\Error\LoaderError; use Twig\Error\RuntimeError; use Twig\Error\SyntaxError; class HelloController { /** * @var Render */ private $render; public function __construct(Render $render) { $this->render = $render; } /** * @param ServerRequestInterface $request * @param ResponseInterface $response * @return ResponseInterface * @throws LoaderError * @throws RuntimeError * @throws SyntaxError */ public function show(ServerRequestInterface $request, ResponseInterface $response) { $response->getBody()->write($this->render->render('hello.twig', ['name' => $request->getAttribute('name')])); return $response; } } 

,


app/Provider/WebProvider.php
 <?php // app/Provider/WebProvider.php namespace App\Provider; use App\Controller\HelloController; use App\Controller\HomeController; use App\Support\ServiceProviderInterface; use Psr\Container\ContainerInterface; use Slim\Interfaces\RouteCollectorInterface; use Slim\Interfaces\RouteCollectorProxyInterface; use Twig\Environment; use UltraLite\Container\Container; class WebProvider implements ServiceProviderInterface { public function register(Container $container) { /* *   */ $container->set(HomeController::class, function (ContainerInterface $container) { return new HomeController($container->get(RouteCollectorInterface::class)->getRouteParser()); }); $container->set(HelloController::class, function (ContainerInterface $container) { return new HelloController($container->get(Environment::class)); }); /* *   */ $router = $container->get(RouteCollectorInterface::class); $router->group('/', function(RouteCollectorProxyInterface $router) { $router->get('', HomeController::class . ':index')->setName('index'); $router->get('hello/{name}', HelloController::class . ':show')->setName('hello'); }); } } 


bootstrap.php
 <?php // bootstrap.php // ... use App\Provider\WebProvider; // ... $providers = [ // ... WebProvider::class, // ... ]; // ... 

- ( )...


 php -S localhost:8080 -t public public/index.php 

тАж http://localhost:8080 , http://localhost:8080/hello/world


world'.
http://localhost:8080/hello/ivan ivan'.


, , http://localhost:8080/helo/world 404 .


4.


route:list


app/Command/RouteListCommand.php
 <?php // app/Command/RouteListCommand.php namespace App\Command; use Slim\Interfaces\RouteCollectorInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; class RouteListCommand extends Command { /* *    ,        */ const NAME = 'route:list'; /** * @var RouteCollectorInterface */ private $router; public function __construct(RouteCollectorInterface $router) { $this->router = $router; parent::__construct(); } protected function configure() { $this->setName(self::NAME) ->setDescription('List of routes.') ->setHelp('List of routes.') ; } protected function execute(InputInterface $input, OutputInterface $output) { $io = new SymfonyStyle($input, $output); $io->title('Routes'); $rows = []; $routes = $this->router->getRoutes(); if (!$routes) { $io->text('Routes list is empty'); return 0; } foreach ($routes as $route) { $rows[] = [ 'path' => $route->getPattern(), 'methods' => implode(', ', $route->getMethods()), 'name' => $route->getName(), 'handler' => $route->getCallable(), ]; } $io->table( ['Route', 'Methods', 'Name', 'Handler'], $rows ); return 0; } } 

,


app/Provider/CommandProvider.php
 <?php // app/Provider/CommandProvider.php namespace App\Provider; use App\Command\RouteListCommand; use App\Support\CommandMap; use App\Support\ServiceProviderInterface; use Psr\Container\ContainerInterface; use Slim\Interfaces\RouteCollectorInterface; use UltraLite\Container\Container; class CommandProvider implements ServiceProviderInterface { public function register(Container $container) { /* *       */ $container->set(RouteListCommand::class, function (ContainerInterface $container) { return new RouteListCommand($container->get(RouteCollectorInterface::class)); }); /* *        */ $container->get(CommandMap::class)->set(RouteListCommand::NAME, RouteListCommand::class); } } 


bootstrap.php
 <?php // bootstrap.php // ... use App\Provider\CommandProvider; // ... $providers = [ // ... CommandProvider::class, // ... ]; // ... 

...


 ./bin/console route:list 

тАж :


 Routes ====== --------------- --------- ------- ------------------------------------- Route Methods Name Handler --------------- --------- ------- ------------------------------------- / GET index App\Controller\HomeController:index /hello/{name} GET hello App\Controller\HelloController:show --------------- --------- ------- ------------------------------------- 

, , !


, Slim тАФ routes.php ( ), . тАФ , , .


Source: https://habr.com/ru/post/hi452834/


All Articles