Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHPer人生、一度はフレームワークを作っておこう!

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for uzulla uzulla
April 16, 2016

 PHPer人生、一度はフレームワークを作っておこう!

PHPカンファレンス北海道 2016 発表資料
20160416

Avatar for uzulla

uzulla

April 16, 2016
Tweet

More Decks by uzulla

Other Decks in Programming

Transcript

  1. ༗໊ͳFW Symfony, Laravel, Lumen, Slim Framework, Yii, PHPixie, FuelPHP, CodeIgniter,

    CakePHP, ZendFramework, Phalcon, Nette, Silex, fatfree, limonade, DietCake, DietCube, Lithium, Aura, Ethna, etc. etc. 㙽ʹ֯୔ࢁ
  2. FWΛ࢖͏ཧ༝ - ੜ࢈ੑͷ޲্ - ܾ·Γ੾ͬͨίʔυΛॻ͔ͣʹࡁΉ - ྑ͋͘Δػೳ͸ϓϥάΠϯ͕͋Δ͜ͱ΋ - ʮ੍ݶʯ͕Ͱ͖Δ͜ͱͰɺઃܭ͕͠΍͍͢ -

    ඼࣭ͷ޲্ - ϩδοΫʹूதͰ͖ɺ৽نίʔυྔΛݮΒͤΔ - ʮྑ͍ઃܭʯ͔Βဃ཭ͮ͠Β͘ͳΔ - ηΩϡϦςΟϗʔϧ͕উखʹຒΊΒΕ͍ͯΔࣄ΋ଟ͍ - େن໛։ൃͷجૅʹͳΓ΍͍͢ - νʔϜʹن໿Λཁٻ͠΍͍͢ - ʢେ఍ʣγοΧϦͨ͠υΩϡϝϯτ͕ଘࡏ͢ΔͷͰֶशɾڭҭ͠΍͍͢
  3. ʮςϯϓϨʔτΤϯδϯ΋ॏཁͩʯ » ςϯϓϨʔτΤϯδϯͱͯ͠PHP͸ΞϧςΟϝοτ » ηΩϡΞ͞Λపఈ͢Δͷ͕Ή͔ͣ͗͢͠Δ <?php echo $_GET['foo']; ?> »

    ͜͜ʹ͍Δਓ͕ॻ͘ͱ͸ࢥ͑ͳ͍͕ɺ΢οΧϦॻ͚ ͪΌ͏ » ʢBlogΧελϜҊ݅ͩͱׂͱݟΔ…ίϫΠ…ʣ » ʮੈքฏ࿨ͷҝʹPHPͷྗΛ෧ҹ͢Δඞཁ͕͋Δʯ
  4. ׬!

  5. Routing, Middleware, Controllers, Requests, Responses, Views, Blade Templates, Authentication, Authorization,

    Artisan Console, Billing, Cache, Collections, Elixir, Encryption, Errors & Logging, Events, Filesystem / Cloud Storage, Hashing, Helpers, Localization, Mail, Package Development, Pagination, Queues, Redis, Session, SSH Tasks, Task Scheduling, Testing, Validation, Query Builder, Migrations, Seeding, Eloquent ORM,
  6. <?php // index.php require_once(dirname(dirname(__FILE__)) . "/app/ore.php"); define("DB_DSN", 'sqlite:' . dirname(dirname(__FILE__))

    . "/db.sqlite"); option('HTML_TITLE', "ͳ͔ͭ͠ͷੈքͰ͢"); route('/', 'post_list'); route('/post/create', 'post_create'); route('/post/:id', 'post_show'); route('/reset', 'post_reset'); run(); ?>
  7. function route($path = null, $func_name = null) { // ؔ਺ऴྃ࣌ʹ΋ফ͑ͳ͍഑ྻͱͯ͠$route_listΛએݴ

    static $route_list = array(); // $keyͱ$val྆ํʹԿ͔ೖ͍ͬͯΕ͹ɺ$pathΛΩʔʹ$func_nameΛอଘ if (!is_null($path) && !is_null($func_name)) $route_list[$path] = $func_name; // Ҿ਺ࢦఆແ͠ͳΒɺ$route_listΛ·Δ͝ͱฦ͢ if (is_null($path)) return $route_list; // $pathҾ਺͕༗ΓɺͦͷΩʔ͕route_listʹ͋Ε͹ɺͦΕΛฦ͢ if (isset($route_list[$path])) return $route_list[$path]; // Έ͔ͭΒͳ͔ͬͨͷͰɺnullΛฦ͢ return null; }
  8. function find_match_path() { $uri = $_SERVER['REQUEST_URI']; foreach (path_regex() as $path

    => $regex) { if (preg_match($regex, $uri, $matches)) { $match_path = $path; break; } } if (!isset($match_path)) { return 'notfound'; } foreach ($matches as $k => $v) { if (preg_match('/^[0-9]/u', $k)) { continue; } option($k, urldecode($v)); } return $match_path; }
  9. function path_regex() { $regex_list = array(); foreach (route() as $route

    => $cb) { $regex_list[$route] = '#\A' . preg_replace_callback( '#:([\w]+)#', function ($m) { return "(?P<{$m[1]}>[^/]+)"; }, $route ) . '\z#'; // ex: #\A/post/(?P<id>[^/]+)\z# } return $regex_list; }
  10. ػೳ (ݱ࣮) » ϧʔλʔ » TwigͬΆ͍ςϯϓϨʔτΤϯδϯ × » ϩΨʔ »

    PSR-7ɺMiddlewareରԠ˚ » ίϯςφʢϩέʔλʣ » ηογϣϯ ˚
  11. <?php //index.php declare(strict_types=1); include __DIR__."/../vendor/autoload.php"; // Route ొ࿥ $router =

    new \Ore2\Router(); $router->get('/', function(){ return $this->html('<span style="color:red">123</span>'); }); $router->get('/name/:name', function(){ return $this->html("hello {$this->c->routeParams['name']}"); }); $router->get('/sample', '\\MyApp\\SampleAction::sample'); $router->get('/sample_json', '\\MyApp\\SampleAction::sampleJson'); // PSR-7ΦϒδΣΫτͷϑΝΫτϦΛ࣮૷͢ΔͷఘΊ·ͨ͠ $request = \Zend\Diactoros\ServerRequestFactory::fromGlobals(); $response = new \Zend\Diactoros\Response(); // route ղܾ $match_result = $router->findMatch($request->getMethod(), $request->getRequestTarget()); // ֤छϔϧύʔΛίϯςφʹ͍ΕΔ $container = new \Ore2\Container(); $container->config = require __DIR__."/../settings.php"; $container->session = new \Ore2\Session(new \Ore2\Session\Storage\PHPSession()); $container->template = new \Ore2\Template($container->config['template']); $container->logger = new \Ore2\Logger(); // ΞΫγϣϯΛ࡞੒ $action = $match_result->buildAction($container); // Middlewareͱ࣮ͯ͠ߦ $seqencer = new \Ore2\MiddlewareSequencer([ new \Ore2\Transmitter(), $action ]); $seqencer($request, $response);
  12. » ίϯςφ͸ҙຯͳ͘PSR-11(Draft)ʹ΋ରԠ͠ɺ ArrayAccessͱ__get/set΋࣮૷ » Session͸(ҰԠ)PSR-7Ͱಈ͘Α͏ʹ࡞੒ » CSRFΨʔυ΍ྫ֎τϥοϓ౳ΛPSR-7 Middleware ͱ࣮ͯ͠૷ »

    relay(relayphp.com)෩ͷϛυϧ΢ΣΞ࣮ߦػೳΛ ༻ҙ » ϧʔτઃఆͰɺΞΫγϣϯʹΫϩʔδϟΛ౉ͯ͠΋ bindToͰ$thisܦ༝Ͱ৭ʑ৮ΕΔ » etc,etc
  13. ͳʹ͕خ͍͠ͷʁ » ී௨͸ɺಛʹ͏Ε͘͠ͳ͍ » ݸਓతʹ͸ » ΦϨΦϨFWѪ޷Ոతʹ͸ָʹςετͰ͖ͦ͏ » ଞͷݴޠͬΆͯࣗ͘વʹײͯ͡خ͍͠ »

    ReactPHP౳ΞϓϦέʔγϣϯαʔόʔ͕ରԠ͢ Ε͹ָͦ͠͏ʂ=>࣮ࡍπΠʔτΛݟͨ » Middleware͕ͨͷͦ͠͏
  14. // ZendͷPSR-7࣮૷ $request = \Zend\Diactoros\ServerRequestFactory::fromGlobals(); $response = new \Zend\Diactoros\Response(); //

    ΞΫγϣϯΛϧʔλʔͰܾఆ ΞΫγϣϯ = ϧʔλʔ($request); // ࣮ߦ $response = ΞΫγϣϯ($request, $response); // ԿΒ͔ͷํ๏Ͱ$responseΛૹ৴ ૹ৴͢Δ܅($response);
  15. // request͔ΒPOSTऔಘྫ $name = $request->parsedBody['name'] ?? ''; // ϨεϙϯεΦϒδΣΫτ࡞੒ $response

    = $response ->withStatus(200); ->withHeader('Content-Type', 'text/html'); $body = new \Zend\Diactoros\Stream('php://memory', 'w'); $body->write("Hello world"); $response = $response->withBody($body); return $response; // ͜ͷޙͰૹ৴܅ͳͲͰૹ৴͞ΕΔ
  16. PSR-7 middlewareʹ͍ͭͯ » ঢ়ଶ͕άϩʔόϧม਺͔ΒҾ͖͸͕͞ΕͨͷͰɺϑΟ ϧλʔΈ͍ͨͳ͜ͱ͕΍Γ΍͍͢ » Rack Middleware΍Plack Middleware »

    ʮͦ͜ΒͷFWʹ΋ϛυϧ΢ΣΞ͋Δ͡ΌΜʁʯ ʮͦΕ͕શ෦ͷFWͰڞ௨ͷIFʹͳΕ͹ɺເ͕ʁʯ ʮʮ޿͕Δʂʂʯʯ
  17. » Ore » 9 commits / 588 ++ / 168

    -- » Ore2 » 62 commits / 4,106 ++ / 1,063 --
  18. <?php include __DIR__."/../vendor/autoload.php"; \MyApp\Db::$pdo = new \PDO("sqlite:".__DIR__."/../db.sqlite"); $container = [

    'template' => new Twig_Environment( new Twig_Loader_Filesystem(__DIR__."/../template") ) ]; $routing_map = [ ['GET', '/', '\MyApp\Post::showList' ], ['GET', '/post/:id', '\MyApp\Post::show', ['id' => '/^(\d+)$/']], ['POST', '/post/create', '\MyApp\Post::create' ], ['GET', '/reset', '\MyApp\Post::reset' ], '#404' => '\MyApp\Post::notfound' ]; $router = new \Teto\Routing\Router($routing_map); $action = $router->match($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']); if (!preg_match('|\A([\\a-zA-Z0-9_]*)::([a-zA-Z0-9_]+)\z|u', $action->value, $matches)) throw new \InvalidArgumentException('invalid action string:' . $action->value); $method_name = $matches[2]; (new $matches[1]($container))->$method_name($action->param);
  19. » 2 commits / 398 ++ / 0 -- »

    ੡࡞࣌ؒ30෼͆ʂ » ୹͍ʂ
  20. ׬