ã·ã³ãã«ãª PHP7ãã¤ã¯ããã¬ã¼ã ã¯ã¼ã¯ Karen
ãã®è¨äºã¯ PHP7 㧠PSR-7 㨠Middleware ã使ããã¤ã¯ããã¬ã¼ã ã¯ã¼ã¯ãæ¸ãã¦ã¿ã ã®ç¶ç·¨ã§ãã
ã³ã¼ã㯠https://github.com/brtriver/karen
ååã¾ã§ã®è¨äºã®æµãããã£ããã¨æ¸ãã¨
- Slim3 ã PSR-7 㨠Middleware ãæ¡ç¨ãã¦ããã®ã§ãPHP7ã®ç¡åã¯ã©ã¹ã使ã£ã¦ã¿ã
- ãã£ã¨èããã®ã»ã欲ãããªã PHP7㧠PSR-7 㨠Middleware ã使ã£ããã¤ã¯ããã¬ã¼ã ã¯ã¼ã¯ãä½ã£ã¦ã¿ã(Karen v0.1)
ãã ãèãä½ãããã¦ã¨ã³ããã¤ã³ãã®ã³ã¼ãã«è²ã æ¸ããªãã¦ã¯ãªããªããªã£ã¦ãããã¯è¦éããæªããªã£ãã®ã§ããå°ãæ´çããã£ã¤ãæ¸ãã¦ã¿ã(v0.2)
Karen ã使ã£ãã³ã¼ã
解説ã¯ãã¨ã§ããã¾ãã
<?php $app = new YourFramework(); // Karenã¢ããªã±ã¼ã·ã§ã³ãæ¡å¼µããã¢ããªã±ã¼ã·ã§ã³ $app->run(); $app->sendResponse();
ã®ããã«æ¸ããããPHP7ãªã®ã§ãç¡åã¯ã©ã¹ãå©ç¨ãã¦
<?php require __DIR__ . '/../vendor/autoload.php'; $app = new class extends Karen\Framework\Karen { public function action($map) { // hello name controller sample. $map->get('hello', '/hello/{name}', function($args, $controller) { $name = $args['name']?? 'karen'; return $controller->render('[Karen] Hello, ' . $name); })->tokens(['name' => '.*']); return $map; } }; $app->run(); $app->sendResponse();
ã®ããã«æ¸ããã¨ãã§ãã¾ãã
Karen ã®æ§æ
Applicationã®ã¤ã³ã¿ã¼ãã§ã¼ã¹ãç¨æãã¾ãããã¤ã³ã¿ã¼ãã§ã¼ã¹ã§ã¯
- ä½ãããã®ãµã¼ãã¹ã³ã³ãã(DI)ãæ§ç¯ãã
- ä½ãããã®Middlewareãå®ç¾©ãã
- ä½ãããã®ã«ã¼ãã£ã³ã°ãããªã¯ã¨ã¹ãã«ãããããã«ã¼ãã£ã³ã°ã¨å¦çã決å®ãã
- å®ç¾©ããMiddlewareã¨æ±ºå®ããã«ã¼ãã£ã³ã°ã®å¦ç(ã³ã³ããã¼ã©ã¼)ãè¡ã
ã¨ããã«ã¼ã«ã ãã決ãã¦ãã¾ãã
ããã¦ããããã¯`$app->run()` ãå¼ã¶ãã¨ã§é çªã«ã¡ã½ãããå¼ã°ããæ§ç¯ãããã¢ããªã±âã·ã§ã³ããæå¾ã« `$app->sendResponse()` ãå©ããã¨ã§ä½ãããã®ã¬ã¹ãã³ã¹ãè¿ããã¾ãã
ãããããã³ãã¬ã¼ãã¡ã½ãããã¿ã¼ã³ã«ãªã£ã¦ãã¦ããããªæãã§ãã
<?php abstract class Application { .... public function run() { $this->container(); $this->middleware(); $this->route(); $this->response(); } }
ããã¦ãKaren ã¯ãã®Applicationã¤ã³ã¿ã¼ãã§ã¼ã¹ãå®è£ ããApplicationã¯ã©ã¹ããã¼ã¹ã«ã
- ãµã¼ãã¹ã³ã³ããã« Pimple
- Middleware ã®ã©ã¤ãã©ãªã« Relay
- ã«ã¼ãã£ã³ã°ã«Aura.Router (Karen2ã®ãµã³ãã«ã§ã¯FastRoute)
ã使ãããã«å®è£ ãã¦ãã¾ãã
å®éã¯ã«ã¼ãã£ã³ã°ã«ãããããå ´åã®å¦çã¯æ¸ããã¦ããªãã®ã§ããã®Karenã¯ã©ã¹ãæ¡å¼µããå¿
è¦ãããã¾ãã
ããããæåã«æ¸ããç¬èªã¢ããªã±ã¼ã·ã§ã³ã¯ã©ã¹ã使ã£ãã³ã¼ãããç¡åã¯ã©ã¹ã使ã£ãã³ã¼ãã«ãªãã¾ãã
Karen ã®ã³ã³ããã¼ã©ã¼
Karen ã§ã¯ã¢ããªã±ã¼ã·ã§ã³ãã responseã¡ã½ãããã³ã¼ã«ããã¨ãã«ã«ã¼ãã£ã³ã°ã«å®ç¾©ãããcallableãªãã®ãMiddlewareãã¨ããã¦å®è¡ããã¾ãããã®è²¬åãã³ã³ããã¼ã©ã¼ã«ã¾ããã¦ãã¾ããããã¦ãã¢ããªã±ã¼ã·ã§ã³ã§å©ç¨ããã³ã³ããã¼ã©ã¼ãå·®ãæ¿ããäºãå¯è½ã«ãã¦ãã¾ãã
é常ã¯ãcontainerã¡ã½ããã§pimple($c)ã«ä»¥ä¸ã®ããã«ã³ã³ããã¼ã©ã¼ãçªã£è¾¼ãã ãã§ããã
<?php $c['controller'] = new Controller();
Twigãã³ãã¬ã¼ãã使ãã¤ã¤ããã®ããã®ã¡ã½ãã(renderWithT) ã使ããããã«æ¡å¼µãããã®ãå®ç¾©ããããã«ã¯
<?php $c['controller'] = function($c) { $controller = new class extends Controller{ use Templatable; }; $controller->setTemplate($c['template']); return $controller; };
ã®ããã«Controllerã¯ã©ã¹ãTraitãå©ç¨ããã¯ã©ã¹ã«ç¡åé¢æ°ã§æ¡å¼µããã ãã§OKã§ããPHP7便å©ã§ããã
ãã¡ããç¬èªã®ã³ã³ããã¼ã©ã¼ãå®ç¾©ãããã¨ãã§ãã¾ãããæ©è½ã追å ãããã®ã§ããã°ä¸ã®ããã«Traitãç¨æããã°ä»£æ¿äºè¶³ããããããã¾ããã
ã³ã³ããã¼ã©ã¼ã¯ã«ã¼ãã£ã³ã°ã«ä¸è´ããã¨ãã«å¼ã°ããcallableãªãã®ãææ¡ãã¦ãã¾ããããã®ã¯ãã¼ã¸ã£ã¼ã¯å¼æ°ã¨ã㦠$args 㨠$controller ãåãåãã¾ãã
$argsã¯ãã¹ã§å®ç¾©ããåå¾ããããã©ã¡ã¼ã¿ãå
¥ã£ã¦ãã¦ãååãkeyã¨ãã¦ã¢ã¯ã»ã¹ã§ãã¾ãã
ã¾ãã$controllerã¯ã³ã³ããã¼ã©ã¼ã¯ã©ã¹èªèº«ã§ããRequestã¨Responseã«ã¯ $controller->request, $controller->responseã§ã¢ã¯ã»ã¹ã§ãã¾ãã
ãã¡ããããã®Reuqestã¨Response㯠Middleware ãé©ç¨ãããå¾ã®ãªãã¸ã§ã¯ããå
¥ã£ã¦ãã¾ãã
ãã¨ã¯ Middleware ã®ä»æ§ã«å¾ã£ã¦ $response ãè¿ãããã«ãã¾ãã
<?php $map->get('hello', '/hello/{name}', function($args, $controller) { $name = $args['name']?? 'karen'; return $controller->render('[Karen] Hello, ' . $name); })->tokens(['name' => '.*']);
Traitã§è¿½å ããã¡ã½ãããªã©ã$controllerãéãã¦å¼ã³åºããã¨ãã§ãã¾ãã
<?php // with twig $map->get('render_with_twig', '/template/{name}', function($args, $controller) { return $controller->renderWithT('demo.html', ['name' => $args['name']]); });
ã¾ããJsonã®ã¬ã¹ãã³ã¹ãè¿ãããå ´åã¯return ãJsonResponseã«ãªã£ã¦ããã°ããã®ã§
<?php $map->get('json', '/json/{name}', function($args, $controller) { return new \Zend\Diactoros\Response\JsonResponse(['name' => $args['name']]); });
ã®ããã«ããã°ãã¾ãã§ãã¾ã(ãã ããMiddlewareã§é©ç¨ããã¦ãã $controller->response ãç ´æ£ãã¡ããã¾ãã)
Karenãå©ç¨ãã¦ãªã¬ãªã¬ãã¬ã¼ã ã¯ã¼ã¯ã®ä½ã
ã§ãKaren 㯠Applicationã¤ã³ã¿ã¼ãã§ã¼ã¹ãå®è£ ãããã³ãã¬ã¼ããã¿ã¼ã³ã«å¾ã£ãä½ãã«éããªãã®ã§ããã®ãã¿ã¼ã³ã«å¾ã£ã¦ããããã°å¥½ããªãã®ãæ¸ãã°ããã¨æãã¾ãã
éä¸ã§éãã©ã¤ãã©ãª(ã³ã³ãã¼ãã³ã)ã«å·®ãæ¿ãã.. ãªãã¦ãã¨ããã¾ããããªãã¨æãã®ã§ãæåã«ä½¿ãããã³ã³ãã¼ãã³ããããç¨åº¦æ±ºãã¦æ¸ãã¦ãã¾ãã¨ãã§ããããããªãã§ããããã
ãã¨ãã°ããµã³ãã«ã¨ã㦠Aura.Router ã§ã¯ãªã FastRoute ã使ã Karen2 ãä½ãå ´åã¯ãrouteã¡ã½ããã代ãããrouteçµæã使ãresponseã¡ã½ãããããã«ä¼´ã£ã¦æ¸ãæãããã§ãããããã ãã§ãã¨ã®å¦çã¯åãã§ãã
- Aura.Router ç
<?php class Karen extends Application { .... public function route() { $map = $this->c['router']->getMap(); // define routes at an action method in an extended class $map = $this->action($map); $this->route = $this->c['router']->getMatcher()->match($this->request); } public function response() { if (!$this->route) { $response = $this->response->withStatus(404); $response->getBody()->write('not found'); return; } // parse args $args = []; foreach ((array)$this->route->attributes as $key => $val) { $args[$key] = $val; } // add route action to the queue of Midlleware $this->addQueue('action', $this->c['controller']->actionQueue($this->route->handler, $args)); } }
- FastRoute ç
<?php class Karen extends Application { .... public function route() { $this->c['handlers'] = function () { return $this->handlers(); }; $dispatcher = $this->c['dispatcher']; $this->route = $dispatcher->dispatch($this->request->getMethod(), $this->request->getUri()->getPath()); } public function response() { switch ($this->route[0]) { case \FastRoute\Dispatcher::NOT_FOUND: echo "Not Found\n"; break; case \FastRoute\Dispatcher::FOUND: $handler = $this->route[1]; $args = $this->route[2]; $this->addQueue('action', $this->c['controller']->actionQueue($handler, $args)); break; default: throw new \LogicException('Should not reach this point'); } } }
ã¡ãªã¿ã«ããã¼ã«ã«ã§ãã³ãåãã¨ãå§åçã« FastRoute éãã§ãã
Middleware ã©ã¤ãã©ãªãå°å ¥ãã¦ã¿ã
Karen 㯠Middleware ãæã£ã¦ããã®ã§ãpsr7-middlewares ãç°¡åã«ä½¿ãã¾ã
composer require oscarotero/psr7-middlewares
ã§ã¤ã³ã¹ãã¼ã«ããã°ãã¨ã³ããã¤ã³ãã®ã³ã¼ãã§middlewareãqueueã«è¿½å ããã ãã§ã
<?php require __DIR__ . '/../vendor/autoload.php'; $app = new class extends Karen\Framework\Karen { // middleware ã追å ãã public function middleware() { $this->addQueue('responseTime', Psr7Middlewares\Middleware::responseTime()); } public function action($map) { // hello name controller sample. $map->get('hello', '/hello/{name}', function($args, $controller) { $name = $args['name']?? 'karen'; return $controller->render('[Karen] Hello, ' . $name); })->tokens(['name' => '.*']); return $map; } }; $app->run(); $app->sendResponse();
ããã§ã¬ã¹ãã³ã¹ãããã«å¦çæéã追å ãããã¨ãã§ãã¾ããã
X-Response-Time:8.789ms
便å©ã
Karen ãä½ã£ã¦ã¿ã¦
- ç¡åã¯ã©ã¹ã¯ããã£ã¨ããã®ã«ã¯æããªå ´é¢ã¯ããããã¨ãã°ãã¹ãã§ç¡åã¯ã©ã¹ã使ã£ã¦å¼ã³åºãé åºãæ£ãããã©ãã®ã³ã¼ããæ¸ããã
<?php class ApplicationTest extends \PHPUnit_Framework_TestCase { public function testRunOrder() { $app = new class extends Application{ public $passed = ''; public function container() { $this->passed .= 'container->'; } public function middleware() { $this->passed .= 'middleware->'; } public function route() { $this->passed .= 'route->'; } public function response() { $this->passed .= 'response'; } }; $app->run(); $this->assertSame('container->middleware->route->response', $app->passed); } }
- Middleware ã«ä¹ã£ãã¦ããã°ãè²ããªã©ã¤ãã©ãªããã®ã¾ã¾ä½¿ããã¡ãªããã¯å¤§ããããã¨ãã°psr7-middlewares
- PSR-7 ã«æºæ ããRequestãResponseã£ã¦ãããªã«ç¡ãããå·®ãæ¿ããããªãå ´é¢ã£ã¦æãæµ®ãã°ãªãã
- ããç¨åº¦æºåããããã¬ã¼ã ã¯ã¼ã¯ã®ã»ãããªã¬ãªã¬ãã¬ã¼ã ã¯ã¼ã¯ãã楽ã
- ã¡ã½ããã®æ»ãã®åãå®ç¾©ã§ããã®ã§ãã¡ããã¨è½ã¡ã¦ãããã®ã¯æ¥½(ãã ãå®è¡æ)