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

大統一PHP

uzulla
March 09, 2018

 大統一PHP

PHPerKaigi 2018 前夜祭🍻
2018/03/09 at coconeri

uzulla

March 09, 2018
Tweet

More Decks by uzulla

Other Decks in Programming

Transcript

  1. େ౷ҰPHP
    2018/03/09
    PHPerKaigi 2018 લ໷ࡇ

    View Slide

  2. uzullaͰ͢

    View Slide


  3. View Slide

  4. View Slide

  5. https://www.youtube.com/watch?v=2tZxNtn0kDc
    • PerlͷΧϯϑΝϨϯεͰPHPͷ࿩ͰϕεττʔΫ໯ͬͨ΍ͭ
    • ʢ݁Ռɺ৆඼Ͱւ֎ΧϯϑΝϨϯεʹɺӳޠ͕Θ͔ΒΜPHPer
    ͕ɺӳޠͰPerlτʔΫΛ͠ʹߦ͘Ӌ໨͜ͱʹͳͬͨɺΊͬͪΌ
    Α͔ͬͨʣ
    • ΋͏಺༰͸ݹ͍ʢ·ͩPHPΛ஌Βͳ͍ਓʹ͸ྑ͍͔΋ʣͷͩ
    ͕ɺ͍·ͩʹײ૝Λ͍ͨͩ͘

    View Slide

  6. View Slide

  7. https://www.youtube.com/watch?v=XOlSMGHhfrY
    • php.iniʹ͍ͭͯ̍࣌ؒҎ্ʁͨͬ΀Γ࿩ͨ͠
    • ·͋ɺPHPerͳΒݺٵͱಉ͘͡Β͍׳Ε͍ͯΔࣄͩͱ͸ࢥ͏
    • ·ͩ໾ʹͨͭͱࢥ͏ʢͨͿΜʣ

    View Slide

  8. View Slide

  9. https://www.youtube.com/watch?v=bVRgVgEf9Ho
    • ʮPHPͰεϚϗΞϓϦʂʯʮPHPͰεϚʔτσδλϧΧϝϥʂʯ
    • ࢓ࣄʹ͸໾ཱͨͳ͍੒෼ଟΊ
    • PHP͕޷͖ͳͷͰ
    • ࣗ෼ͷझຯͰ͢

    View Slide

  10. ͸͍

    View Slide

  11. DISCLAIMER
    • ͜ͷτʔΫ͸ٕज़తͳڵຯΛຬͨͨ͢Ίͷख๏Ͱ͋Γɺৗ༻͢
    ΂͖ͱ͸͍͑ͳ͍ख๏ؚ͕·Ε͍ͯ·͢ɻ
    • ʮ͏͚͝͹͍͍ʢ΍ͬͯΈͨΒ͏͍ͨ͝ʣʯతͳख๏΋͋Γ·
    ͢ɻ
    • ۀ຿ʹ࢖͏લʹಉ྅ͱ૬ஊ͠·͠ΐ͏ʂ

    View Slide

  12. ຊ୊

    View Slide

  13. ʮ౷Ұʯ
    ɹ
    ʮී௨ʯ

    View Slide

  14. ࢲ͕ײ͡Δ໰୊

    View Slide

  15. Α͋͘Δ෩ܠ
    ʁɿʮPHPͷ؀ڥߏஙΑ͘Θ͔ΒΜʯ
    ࢲɿʮࢲ΋Α͘Θ͔ΒΜɺମ͕͔ͬͯʹಈ͘ʯ

    View Slide

  16. 1, PHPͰΞϓϦΛಈ͔͢ʮ؀ڥʯ͕৭ʑ͋Γ͗͢Δ
    • Apache(+mod_php)
    • Apache with php-cgi
    • nginx with php-fpm+php-cgi(FastCGI)
    • IIS with php-cgi(FastCGIɺPM͸IIS͕ߦ͏)
    • h2o with php-cgi(FastCGIɺPM͸h2o͕ߦ͏ʣ
    • PHP on GAE(ṖͷPHP)
    • HHVMʢ୯ମͰhttpdʹͳΔʣ

    View Slide

  17. ී௨͸(?)
    • nginx౳ͷhttpd + httpΛ஻ΔΞϓϦ
    • 㙽ʹ֯ΞϓϦ͸httpΛ஻Δ
    • ʢPHP͸FastCGI…ΊΜͲ͍…ʣ

    View Slide

  18. 2, PHPΛͲ͔͜Β΋ͬͯ͘Δʁ
    • yum,apt (Linux
    • installer (Windows
    • Brew (Mac
    • php-build (Linux,Mac
    • ໺ྑϏϧυ (tar ball͔ΒϏϧυ
    • ࣗՈrpm

    View Slide

  19. ී௨͸(?)
    • ·͋ɺLLͳΒ͜͜Β΁Μ͸େࠩͳ͍…ͷ͕ͩ
    • goͱ͔͸ϫϯόΠφϦ
    • ʮCͱ͔͸so͕͋Δ͔ΒʯʮsoͳΜͩʯ
    • ʮࠓ͙͢μ΢ϯϩʔυʯ
    • ʮαʔόϨε͸όΠφϦ΋͍Βͳ͍ͧʂʯʮͦ͏͍͏࿩Ͱ͸ͳ
    ͍Ͱ͢…ʯ

    View Slide

  20. PHPόΠφϦ͸৭ʑ͋Δ
    • php(-cli)
    • php-cgi
    • php-fpm(+php-cgi)
    • mod_php(.soɺ.dllʣ
    • PHPerͳΒ͜ΕΒΛ֮ࣗతʹʮ࡞Εʯ·͢ΑͶ

    View Slide

  21. ී௨͸ʢʁʣ
    • ʮී௨͸Ͳ͏ͳͷʁʯʮී௨͸Ұݸ͚ͩͩΑʯ
    • PerlͳΒperlʂʂRubyͳΒrubyʂʂ
    • ʢbundler,cartonͳͲ͸πʔϧͰ͢ʣ
    • ʮmod_perl͸ʁʯʮ΢ο಄͕ʯ
    • ʮmod_rubyʯʮૉਓͳͷͰΈͨ͜ͱͳ͍Ͱ͢ʯ
    • GoͳΒίϯύΠϧޙόΠφϦ

    View Slide

  22. 3, C֦ுʢPeclʣ
    • peclίϚϯυͰάϩʔόϧʹೖΕΔ
    • ໺ྑϏϧυͰάϩʔόϧʹೖΕΔ
    • yum,apt౳ͰೖΕΔ
    • php.iniͰࣄલϩʔυ͢Δ

    View Slide

  23. ී௨͸ʢʁʣ
    • ʮcpanm -lͰϥΠϒϥϦͱಉ༷ʹϩʔΧϧʹೖΕΔʯ
    • ʮbundlerͰϥΠϒϥϦͱಉ༷ʹϩʔΧϧʹೖΕΔʯ
    • ຋༁ɿʢcomposer install͢ΔͱɺvendorͷԼʹC֦ு͕
    ೖΔʣ
    • ※ ·͋͜Ε͸ඞͣͦ͏Ͱ͸ͳ͍͕ɺPHPͩͱ໰౴ແ༻Ͱάϩʔ
    όϧʹೖΔΑͶ
    • ʮpeclͬͯͳʹʁcomposerͰ͸͍Βͳ͍ͷʁΉ͔͍ͣ͠ʂʯ

    View Slide

  24. PHP͸ଉΛ͢ΔΑ͏ʹ͜͜Β΁ΜΛཧղ͠ɺ࢖͏͕…
    • ී௨ɺ͜͜·ͰόϦΤʔγϣϯͳ͍ͷͰɺඇPHPer͸ࠔ࿭
    • Ͱ΋ɺզʑ͸໰୊ʹ͸ͳͬͯͳ͍
    • օ͞Μ͸͍͔͢͝Β
    • PHP͸޿͘࢖ΘΕ͍ͯΔ͔Β੔උ͞Ε͍ͯΔ
    • ͔͠͠ɺීஈgoͳͲΛ࢖͍ͬͯΔਓʹ͸Α͘Θ͔ΒΜΒ͍͠
    • ͜·ͬͨ͜·ͬͨ

    View Slide

  25. ·ͱΊΔͱ
    • ී௨ͷਓ͔Βݟͯɺʮී௨ʯͰ͸ͳ͍PHP
    • (ʮී௨ʯͷఆٛ͸͜͜Ͱ͸͠·ͤΜʂʂ)
    • அઈΛײ͡Δ…
    • ʮΑ͠ɺී௨ʢʁʣʹ͋Θ͍ͤͯ͜͏ʂʯ

    View Slide

  26. ʮ౷Ұ͍ͯͧ͘͠ʂʯ

    View Slide

  27. ͸͍

    View Slide

  28. ͱɺ͍͏͜ͱͰ

    View Slide

  29. ͱΓ·ɺhttpdʹͳΖ͏ʂʢʁʣ

    View Slide

  30. ࠶ܝʣଞͷݴޠͰ͸…
    • go → ࣗ෼͕httpdʹͳΔ
    • ruby → ࣗ෼͕httpdʹͳΔ
    • Perl → ࣗ෼͕httpdʹͳΔ
    • PHP → Apache౳͕͍Δ

    View Slide

  31. ʮͱʹ͔͘httpdʹͳΔͷ͕ී௨ʂ
    Զ͸ී௨ʹͳ͍ͬͯͧ͘ʂʂʂʯ
    • ※ ཁग़య
    • ※ ಠࣗղऍ

    View Slide

  32. ΋ͪΖΜզʑ΋httpdʹ
    ͳΕ·͢

    View Slide

  33. (Builtin Serverʁ͋Ε͸։ൃ༻͔ͩΒ…)

    View Slide

  34. ͱ͍͏͜ͱͰ
    ΍ͬͯΈΑ͏

    View Slide

  35. Slim framework
    Ͱ࣮૷ྫ

    View Slide

  36. ී௨ͷslim
    require "vendor/autoload.php";
    $container = new \Slim\Container;
    $app = new \Slim\App($container);
    $app->get('/', function ($request, $response) {
    return $response->write("hello!!");
    });
    $app->run();

    View Slide

  37. ReactPHPΛ͔ͭͬͨ
    Slim

    View Slide

  38. react஌Βͳ͍ਓ΁
    • ΠϕϯτۦಈͰ༷ʑͳॲཧΛ͢ΔϥΠϒϥϦ
    • ͳΜͰ΋ਓͱมΘͬͨ͜ͱ͕޷͖ͳਓʹ͸͓͢͢Ί
    • PHP୯ମͰhttpdʹͳΕΔκʂ
    • (ผͷεϥΠυͰઆ໌ͯ͠·͢)

    View Slide

  39. require "vendor/autoload.php";
    $loop = React\EventLoop\Factory::create();
    $server = new \React\Http\Server(array(
    function (\Psr\Http\Message\ServerRequestInterface $request) {
    $container = new \Slim\Container;
    $app = new \Slim\App($container);
    // !slimͷrequestΛɺreact͕࡞ͬͨ΋ͷʹࠩ͠ସ͑
    $container['request'] = function ($container) use ($request) {
    return $request;
    };
    // ಛʹมΘΒͣ
    $app->get('/', function ($request, $response) {
    return $response->write("hello!!");
    });
    // !Ҿ਺ʹtrueΛ͍ΕΔͱɺresponse ͕ؼ͖ͬͯ·͢ͷͰɺͦΕΛreact΁
    return $app->run(true);
    }
    ));
    $socket = new React\Socket\Server(8888, $loop);
    $server->listen($socket);
    $loop->run();

    View Slide

  40. demo
    $ php main.php
    • ͸ͱ͘ʹ͠·ͤΜʂޙͰʹͨΑ͏ͳ͜ͱ΍Δ

    View Slide

  41. SlimͱreactPHP͸PSR-7ରԠͳͷͰ
    • ͜Μͳ෩ʹͿͬ͜Ί͹ಈ͘ʢ͸ͣʣ
    • ϫϯλονͰҠ২͕Ͱ͖ΔΘ͚Ͱ͸ͳ͍
    • PSR-7 ରԠͱ͸ͦ͏͍͏ҙຯͰ͸ͳ͍
    • ͜Ε͸ผʹߴ଎Ͱ͸ͳ͍ʢ࠷దԽ΍γϯάϧτϯԽ౳ͯ͠ͳ
    ͍ʣ
    • ϒϩοΩϯάΛߟ͑ΔͱΉ͠Ζ஗͍ࣄ΋

    View Slide

  42. օ͞Μʣʮ͋Ε…ʁҙ֎ͱ؆୯ͳͷͰ͸…ʁʯ

    View Slide

  43. ͦΕ͸Ͳ͏͔ͳʁ

    View Slide

  44. ʮී௨ʯͷͨΊʹɺ৭ʑ΍Δ͜ͱ͸͋Δ
    • httpdͷ୅ΘΓʹ੩తϑΝΠϧ഑৴ʢAPIͳΒෆཁ͕ͩ
    • ΤϥʔϋϯυϦϯά
    • ϩΨʔ
    • ηογϣϯʢCSRF౳ͷͨΊʣ
    • ޙड़͠·͢
    • etc...

    View Slide

  45. ༨ஊ PSR-7ͱ͸(ৄࡉ͸άάͬͯ)
    • ͍ΘΏΔʮ$_POSTͰಡΈࠐΈɺechoͰग़ྗʯΛ͠ͳ͍
    • request/responseΦϒδΣΫτΛಡΜͩΓੜ੒ͨ͠Γͯ͠ɺ
    ೖग़ྗΛOOPͰऔΓѻ͏
    • ʮ̍ϦΫΤετ̍ϓϩηεʯͷϝϦοτͰ͋Δεʔύʔάϩʔ
    όϧΛഉআ͠ɺʮNϦΫΤετɺ̍ϓϩηεʯΛ࣮ݱͨ͠Γɺς
    ελϒϧʹͨ͠ΓɺϞδϡϥʔԽʢϛυϧ΢ΣΞԽʣ͕Ͱ͖Δ
    Α͏ʹͳΔͳͲ͕͋Δɻ

    View Slide

  46. ࣮ࡍʹαϯϓϧΞϓϦΛҠ২ͯ͠Έͨ
    • Tinitterͱ͍͏ɺ੿ஶʮWebΞϓϦΤϯδχΞཆ੒ಡຊʯͷα
    ϯϓϧܝࣔ൘ΞϓϦΛҠ২
    • ʢPHP7ରԠͨ͠ΓɺSlim Framework3ʹରԠͤͨ͞Γɺ
    ORMΛ౤ࣺ͛ͯͨΓ͢Δͷʹ͕͔͔࣌ؒͬͨ…ʣ
    • https://github.com/uzulla/Tinitter
    • (ͷ reactize ϒϥϯν)

    View Slide

  47. demo
    • վमલͷී௨ͷTinitter
    • Ͳ͏ͱ͍͏͜ͱ͸ͳ͍͕ɺBuiltin serverͰ͏͔͝͠ͱΔͧ
    ͱ͍͏࿩ɻ

    View Slide

  48. reactͱSlimΛͭͳ͙
    • ͜͜͸͢Ͱʹઆ໌ࡁΈͳͷͰলུ

    View Slide

  49. ੩తϑΝΠϧ഑৴
    • ͜Ε͸؆୯ɺϛυϧ΢ΣΞΛΞϓϦͷલʹࠩ͠ࠐΉ͚ͩ
    • ʢϛυϧ΢ΣΞʹ͍ͭͯ͸ޙड़ʣ
    • ΞϓϦΑΓલʹ͜͞͠Ί͹ɺϑΝΠϧ͕ͳ͚Ε͹ΞϓϦʹ౸ୡ
    ͢Δ
    new WebrootPreloadMiddleware(__DIR__."/htdocs"),

    View Slide

  50. ༨ஊ ϛυϧ΢ΣΞͱ͸ʁ
    • PSR-7(ҎޙPSR-15΋ؚΉ)ରԠͷϛυϧ΢ΣΞͱ͸ɺελο
    Ϋͨ͠ϛυϧ΢ΣΞΛReq/ResΦϒδΣΫτΛ௨ա༷ͤͯ͞ʑ
    ͳલॲཧɺޙॲཧΛߦ͏ɻ
    • CSRFɺΞΫηε੍ݶɺηογϣϯͳͲɻ
    • PSR-7ରԠͷʮϑϨʔϜϫʔΫʯ͸ɺجຊϛυϧ΢ΣΞͱͯ͠
    ࣮૷͞ΕΔɻ

    View Slide

  51. 1
    1 quote the image from http://www.darrenmothersele.com/blog/2017/03/28/php-middleware/

    View Slide

  52. $server = new Server(array(
    // ΤϥʔϋϯυϦϯά ʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹ
    function (ServerRequestInterface $request, callable $next) {
    return $next($request);
    /* ུ */
    },
    // ੩తϑΝΠϧ഑৴ ʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹ
    new WebrootPreloadMiddleware(__DIR__."/htdocs"),
    // ηογϣϯ ʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹ
    new SessionMiddleware(/* ུ */),
    // csrfରࡦ ʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹ
    function (ServerRequestInterface $request, callable $next) {
    /* ུ */
    return $next($request);
    },
    // ΢ΣϒΞϓϦ ʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹ
    function (ServerRequestInterface $request) {
    $app = new \Slim\App($container);
    /* ུ */
    return $app->run(true); // ΢Σϒຊମ࣮ߦɺ͜͜Ͱ͸next͕ͳ͍
    }
    ));

    View Slide

  53. ݟ͑ͳ͍ͷͰൈਮ֦େ

    View Slide

  54. $server = new Server([ // ഑ྻͰϛυϧ΢ΣΞΛొ࿥͢Δ
    // !ΤϥʔϋϯυϦϯάϛυϧ΢ΣΞ ʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹ
    function ($request, $next) { // " req(Πϯελϯε)ͱnext(ؔ਺)ΛऔΔ
    return $next($request); // " ࣍΁
    /* ུ */
    },
    // !੩తϑΝΠϧ഑৴ϛυϧ΢ΣΞ ʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹ
    new WebrootPreloadMiddleware(__DIR__."/htdocs"), // " $this->__invoke()
    // !΢ΣϒΞϓϦʢϛυϧ΢ΣΞʣ ʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹʹ
    function ($request) { // ͜͜͸࣍(next)͕ͳ͍
    $app = new \Slim\App($container);
    /* ུ */
    return $app->run(true); // " ΢ΣϒΞϓϦຊମ࣮ߦɺres(Πϯελϯε)Λreturn
    }
    ]);

    View Slide

  55. • ελοΫ͕RequestΠϯελϯεΛϦϨʔ͢ΔΑ͏ʹ্͔ΒԼ
    ʹ࣮ߦ͞Εɺ
    ɹ$next($request)ͰResponseΠϯελϯε্͕ʹ·ͨ໭ͬͯ
    ͍͘ɻ
    • ్தͰ্ʹฦͯ͠͠·͏͜ͱ΋Ͱ͖Δ
    • ੩తϑΝΠϧ഑৴ͰฦͤΕ͹ɺͦͷԼʹ͸͍͔ͳ͍
    • ͜ͷ͋ͨΓɺ࠷ۙͰ͸PSR-15ͰҾ਺ͷ༷͕ࣜมΘΔ
    ɹʢ͕ɺجຊ͸ಉ͡ʣ

    View Slide

  56. ༨ஊʢύον͕ඞཁͰͨ͠ʣ
    • ͦͷ··Ͱಈ͔ͳ͔ͬͨ
    • mimeΛर͑ͳ͍ͱɺnull͕Ͱ͖ͯͯམͪΔ
    • PatchedWebrootPreloadMiddlewareʹίϐͬͯಀ͛ͨ

    View Slide

  57. ΤϥʔϋϯυϦϯά
    • ΤϥʔϋϯυϦϯά͕ඞཁ
    • ௨ৗΤϥʔ͕ը໘ʹ͸ग़ͳ͍ɺϩάʹ΋ग़ͳ͍

    View Slide

  58. function (ServerRequestInterface $request, callable $next) {
    $promise = new React\Promise\Promise(
    function ($resolve) use ($next, $request) {
    $resolve($next($request));
    }
    );
    // ྫ֎͕͕͋ͬͨΒɺ!͕࣮ߦ͞ΕΔ
    return $promise->then(null, function (Throwable $e) { // Throwable͕ྑ͍ͱࢥ͏
    error_log("ERROR:" . $e->getMessage());
    error_log($e->getTraceAsString());
    return new Response(
    500,
    array(),
    'Internal Server error'
    );
    });
    },

    View Slide

  59. • ϛυϧ΢ΣΞͱͯ͠ɺྫ֎ΛͳΜͰ΋Ωϟον͢Δ܅Λ࡞Δ
    • ྫ֎͕͕͖͋ͬͯͨΒɺΩϟονͯ͠Τϥʔը໘Λදࣔ͢Δ
    • ྫ֎ͷ଴ͪड͚͸reactͷPromiseΛ͔ͭͬͯ଴ͪड͚
    • ମࡋ͸झຯͰ͢Ͷɺࣗ͝༝ʹͲ͏ͧ

    View Slide

  60. ηογϣϯ
    • ϩάΠϯ΍CSRF౳ͷͨΊʹඞཁ
    • PSR-7ʹ͸ʮηογϣϯ͸औΓܾΊ͕ͳ͍ʯ
    • $_SESSION͸εʔύʔάϩʔόϧͳͷͰ
    ʮಉ࣌NϦΫΤετ1ϓϩηεʯෆՄ
    • $_SESSIONʹ͋·΍͔͞ΕͨPHPerʹ͸ͩΔ͍
    • ͱ͸͍͑ϛυϧ΢ΣΞͰ࣮૷͞Εͨ΋ͷ΋͋Δ

    View Slide

  61. // ηογϣϯ
    new \WyriHaximus\React\Http\Middleware\SessionMiddleware(
    'MySessionCookie',
    $cache, // Instance implementing React\Cache\CacheInterface
    [ // Optional array with cookie settings, order matters
    0, // expiresAt, int, default
    '', // path, string, default
    '', // domain, string, default
    false, // secure, bool, default
    false // httpOnly, bool, default
    ]
    ),

    View Slide

  62. ༨ஊ
    • PSR-7ରԠͷηογϣϯ͸৭ʑ͋Δ͕ɺCookieʹ͍ΕΔ΍͕ͭ
    ଟ͍(ྫ:psr7-sessions/storageless)
    • PHPerͱͯ͠͸ɺΘ͔ΔɺΘ͔Δͷ͕ͩ…΢ʔϜ…ͱͳͬͯ͠·
    ͏͕ɺલड़ͷ͸େৎ෉ɺσʔλΛαʔόͰ࣋ͭ
    • σϑΥϧτͷετϨʔδ͸ΦϯϝϞϦͳͷͰɺࣗ෼ͰετϨ
    ʔδΛ࣮૷(React\Cache\CacheInterfaceΛ࣮૷ͨ͠΋
    ͷ)͢ΔͱΑ͍ͩΖ͏ɻ

    View Slide

  63. CSRFTokenͷ࿩ʹ໭Δ
    • Slim Framework 3ͷAddonͷCSRFGuard͸$_SESSIONΛͭ
    ͔͍ͬͯΔͷͰ͏͔͝ͳ͍
    • ΑͬͯɺઌఔͷSessionMiddlewareΛ͔ͭͬͯࣗ෼Ͱ࣮૷͢
    Δ

    View Slide

  64. function (ServerRequestInterface $request, callable $next) {
    // read session
    $session_obj = $request->getAttribute(SessionMiddleware::ATTRIBUTE_NAME);
    $session = $session_obj->getContents();
    if(!isset($session['csrf_token'])) {
    $session_obj->setContents(['csrf_token' => random_bytes(64)]);
    }
    $csrf_token = $session_obj->getContents()['csrf_token'];
    // POSTͳΒcheck token
    if(strtolower($request->getMethod()) === "post"){
    $params = $request->getParsedBody();
    if(!isset($params['csrf_token']) || $params['csrf_token'] !== $csrf_token){
    error_log("invalid csrf_token");
    return new Response(400, [], "invalid csrf_token");
    }
    }
    // attributeʹtokenΛอ࣋
    $request = $request->withAttribute('csrf_token', $csrf_token);
    return $next($request);
    },

    View Slide

  65. csrfτʔΫϯΛformʹຒΊࠐΉॴ
    • csrfτʔΫϯΛΫϩʔδϟͰίϯςφʹ͍Ε͓ͯ͘
    • Twig֦ுΛॻ͍ͯ௥Ճ͢Δ

    View Slide

  66. // ίϯςφʹcsrf_tokenΛอ࣋͠ɺTwigϔϧύʹ౉͢
    $csrf_token = $request->getAttribute('csrf_token');
    $container['csrf_token'] = function ($c) use ($csrf_token){
    return $csrf_token;
    };
    $container->view->addExtension(new CsrfExtension($csrf_token));

    View Slide

  67. class CsrfExtension extends \Twig_Extension
    implements \Twig_Extension_GlobalsInterface
    {
    protected $csrf;
    public function __construct($token)
    {
    $this->csrf = $token;
    }
    public function getGlobals()
    {
    return ['csrf' => ['value' => $this->csrf] ];
    }
    public function getName()
    {
    return 'my/csrf';
    }
    }

    View Slide


  68. View Slide

  69. ༨ஊ Attributeʹ͍ͭͯ
    • PSR-7ͷreqʹ͸Attributeͱ͍͏ɺ࣍ͷϛυϧ΢ΣΞʹ౉͢
    req΁͍Ε͓͚ͯΔ৘ใ͕͋Δ
    • (req಺ͳͷͰ)ࣗ෼ΑΓલͷϛυϧ΢ΣΞʹ͸΋Ͳͤͳ͍Αʂ
    • AttributeΩʔ໊͸ແ๏஍ଳࣗ༝ʢϑϦʔμϜʣ
    • ʢηογϣϯ͸ී௨͜͜ͱ͔͖·ͬͯ΄͍͠…ʣ

    View Slide

  70. ϩΨʔ
    • লུ
    • echoͰ΋error_log()Ͱ΋monologͰ΋ಈ͘
    • monologͳΒɺγϯάϧτϯʹ͓ͯ͘͠ͱΦγϟϨʢʁʣ
    • ྫ֎ͷ$e->getMessage()ͱ$e->getTraceAsString()ͩ
    ͠ͱ͖ΌOKͰ͠ΐ

    View Slide

  71. ͱ͍͏͜ͱͰ
    • ͏͘͝Α͏ʹͳͬͨ

    View Slide

  72. require "vendor/autoload.php";
    require __DIR__ . '/config.php';
    use \Psr\Http\Message\ServerRequestInterface;
    use \React\Http\Server;
    use \React\Http\Response;
    $loop = React\EventLoop\Factory::create();
    $cache = new \React\Cache\ArrayCache();
    $server = new Server(array(
    // ΤϥʔϋϯυϦϯά
    function (ServerRequestInterface $request, callable $next) {
    $promise = new React\Promise\Promise(function ($resolve) use ($next, $request) {
    $resolve($next($request));
    });
    return $promise->then(null, function (Throwable $e) {
    error_log("ERROR:" . $e->getMessage());
    error_log($e->getTraceAsString());
    return new Response(
    500,
    array(),
    'Internal Server error'
    );
    });
    },
    // ੩తϑΝΠϧ഑৴
    new \WyriHaximus\React\Http\Middleware\WebrootPreloadMiddleware(__DIR__."/htdocs"),
    // ηογϣϯ
    new \WyriHaximus\React\Http\Middleware\SessionMiddleware(
    'MySessionCookie',
    $cache, // Instance implementing React\Cache\CacheInterface
    [ // Optional array with cookie settings, order matters
    0, // expiresAt, int, default
    '', // path, string, default
    '', // domain, string, default
    false, // secure, bool, default
    false // httpOnly, bool, default
    ]
    ),
    // csrfରࡦ
    function (ServerRequestInterface $request, callable $next) {
    // read session
    $session_obj = $request->getAttribute(\WyriHaximus\React\Http\Middleware\SessionMiddleware::ATTRIBUTE_NAME);
    $session = $session_obj->getContents();
    if(!isset($session['csrf_token'])) {
    $csrf_token = base64_encode(random_bytes(64));
    $session_obj->setContents([
    'csrf_token' => $csrf_token,
    ]);
    }else{
    $csrf_token = $session['csrf_token'];
    }
    // check token
    if(strtolower($request->getMethod()) === "post"){
    $params = $request->getParsedBody();
    if(!isset($params['csrf_token']) || $params['csrf_token'] !== $csrf_token){
    error_log("invalid csrf_token");
    return new Response(400, [], "invalid csrf_token");
    }
    }
    $request = $request->withAttribute('csrf_token', $csrf_token);
    return $next($request);
    },
    // ΢ΣϒΞϓϦ
    function (ServerRequestInterface $request) {
    // SlimॳظԽ
    $container = new \Slim\Container;
    $app = new \Slim\App($container);
    // reactͷrequestΛಥͬࠐΉ
    $container['request'] = function ($container) use ($request) {
    return $request;
    };
    // Register Twig View helper
    $container['view'] = function ($c) {
    $view = new \Slim\Views\Twig(TEMPLATES_DIR_PATH, []);
    $view->addExtension(new \Slim\Views\TwigExtension($c['router'], '/'));
    return $view;
    };
    // csrf_tokenΛอ࣋͠ɺTwigϔϧύʹ౉͢
    $csrf_token = $request->getAttribute('csrf_token');
    $container['csrf_token'] = function ($c) use ($csrf_token){
    return $csrf_token;
    };
    $container->view->addExtension(new \Tinitter\Misc\TwigExt\CsrfExtension($csrf_token));
    // SlimʹϧʔτΛొ࿥
    \Tinitter\Route::registration($container);
    // ࣮ߦ
    return $app->run(true);
    }
    ));
    $socket = new React\Socket\Server(8888, $loop);
    $server->listen($socket);
    $loop->run();

    View Slide

  73. ʮ໛༷͔ͳʁʯ
    • ·͋ɺ੾ͬͨுͬͨͷίʔυͰ͚͢ͲɺGithubʹ͋͛ͯ͋Δͷ
    ͰɺޙͰݟ͍ͯͩ͘͞ɻ
    • https://github.com/uzulla/Tinitter/tree/
    reactize

    View Slide

  74. DEMO
    • ͱ͍ͬͯ΋·͋ɺݟͯͳʹ͕ҧ͏Θ͚Ͱ΋…
    • phpͰ௚઀ىಈ͠ͱΔͳʂͱ͍͏࿩Ͱ͢ɻ

    View Slide

  75. ͜Εͷ͍͍ͱ͜Ζ
    • httpdෆཁʂʂ࠷ߴʂʂʢʁʣ
    • (ଟ͘ͷ৔߹)ςετ΍ϞοΫָ͕ɺαϒϦΫΤετ΍ϦϓϨΠ
    Έ͍ͨͳࣄ΋ָ
    • ͍ͭʹPHPʹ΋γϯάϧτϯ͕…ʂ
    • ϦΫΤετຖͷʮnewʯΛ࡟ݮͰ͖Δʢ͔΋ʣྫ͑͹ςϯϓ
    ϨʔτɺϧʔλɺઃఆͷϩʔυɺϩΨʔɺDB઀ଓ౳
    • ʢͨͩɺطଘͷFW͸·ͣߟྀͯ͠ͳ͍ͷͰࣗ࡞ෆՄආʣ

    View Slide

  76. ͜ΕͷͭΒ͍ͱ͜Ζ
    • εʔύʔάϩʔόϧ($_GET,$_POST,$_SESSION,$_COOKIE)
    ͸࢖͑ͳ͍
    • ࣮ߦίʔυ͕ίέΔͱαʔόʔ͕མͪΔ
    • PHP7͔Β͸ΤϥʔपΓ͕ྫ֎Ͱ੔උ͞ΕͨͷͰɺ͕Μ͹Ε͹
    େৎ෉ʢͨͿΜʣ
    • ʮexitͨ͠Βࢮ͵ʯʮ͠ͳ͍Ͱʯ
    • ʮdieͨ͠Βࢮ͵ʯʮ͠ͳͳ͍Ͱʯ

    View Slide

  77. • max_execution_time, memory_limitͰอޢ͕Ͱ͖ͳ͍
    • ʢ౰ͨΓલ͕ͩʣൿ఻ͷhtaccess͸͔ͭ͑·ͤΜ͆
    • ࣗ࡞ͨ͠ΓɺલஈͷhttpdͰ͔͚͹ྑ͍
    • ҆શੑ΍ߴ଎ԽΛߟ͑ΔͱPDOར༻ͨΊΒ͏
    • react΍amphp͕ఏڙ͢Δ΋ͷΛ͔ͭ͏
    • ʮmysql͸͋ΔͬΆ͍͚ͲϙεάϨ͸ʁʯʮ…redisͱ͔͸
    ͋ΔΑʯʮ΋͏͓ͬͨͧ͜͏ʂʂʯ(ຊՈͰͳ͚Ε͹͋Δࣄ
    ΋͋Δ)

    View Slide

  78. ஫ҙ఺
    • ʢϑϨʔϜϫʔΫ౳Ҏ֎ͷɺຊ࣭ͷʣॲཧ͕࣌ؒ୹͍ͳΒ଎͘
    ͳΔʢ͜ͱ΋͋Δʣ
    • ॏ͍ॲཧ͸େࠩͳ͍͠ɺΉ͠ΖѱԽ͢Δ͜ͱ͕ଟ͍ʢݸਓͷײ
    ૝ʣ
    • APIͳΒ͍͚Δ…ࣄ΋…͋Δ

    View Slide

  79. ʮPHPͷྑ͍఺͕ͳ͍͡Όͳ͍ʁʯ
    • ͸͍
    • PHPͷྑ͍఺Ͱ͋Δʮϩόετʯʮઃܭ͕ద౰Ͱ΋͋Δఔ౓ಈ
    ͘ʯ͕݁ߏͳ͘ͳΔ
    • ϑΝΠϧΛߋ৽ͨ͠Β࠶ىಈ͕ඞཁʹͳΔ
    • ϒϩοΩϯάͨ͠ΒࢮɺόονతͳॲཧΛͨ͠Β٧·ΔʢͷͰ
    ੾Γ཭͢ʣ

    View Slide

  80. ͦΕͰ΋…
    • httpd͍Βͳ͍ɺphp͸php(-cli)͚ͩͰ͍͍ɻ
    • νϡʔχϯά͢Ε͹ɺܰྔͳ༻్ͳΒૣ͍ʢ͜ͱ΋͋Δʣ
    • ʮຊ෺ͷγϯάϧτϯ͕΄͔ͬͨ͠Μͩ…ʯ
    • ׽ͷϩϚϯ͕͋Δʢಠࣗղऍʣ

    View Slide

  81. httpdΛphpʹ౷ҰͰ͖
    ͨͧʂʢʁʣ

    View Slide

  82. ͸͍

    View Slide

  83. ͔͜͜Β༨ஊ
    εϥΠυͰݟͯΔਓ޲͚
    ͕࣌ؒ༨ͬͨΒ࿩͠·͢

    View Slide

  84. ͜͏͍ͬͨΠϕϯτۦಈͷͳʹ΍Βྫ
    • reactPHP
    • areys
    • swoole

    View Slide

  85. reactPHP
    • https://github.com/reactphp/http
    • ఀ଺͍͕ͯͨ͠ɺ෮׆ʂ
    • …ͱ͓΋͍͖΍ɺਖ਼݄ऴΘͬͨΒ·ͨࢭ·ͬͨ
    • ͱ͸͍͑ɺhttpd͍ͩͿྑ͘ͳͬͨɻͪΐͬͱલ·Ͱ͸ɺʮॻ
    ͘͜ͱ΋Ͱ͖ΔΑʂʯͱ͍͏αϯϓϧίʔυͬΆ͍ײͩͬ͡
    ͨɻ
    • POSTͷ࣮૷͕؆қ͗͢Δ౳͕͋ͬͨ

    View Slide

  86. reactPHP ͸ PSR-7ରԠ
    • PSR-7ରԠͰ࣮૷͞ΕͨͷͰɺPSR-7ରԠͷFW͕৐Δʂ
    • …ͱ͍͏ͷ͸ӕͰ͢ɻଟ͘ͷFW͸άϩʔόϧΫϦʔϯͰͳ͍
    (ಛʹɺηογϣϯͳͲ)
    • ଟগؾΛ͚ͭΕ͹͍͚Δ
    • PSR-7ඇରԠͰ΋Laravel(ྫ:mnvx/laravel-reactphp)΍
    Symfony͸όΠϯσΟϯά͕͋Δʢ͕…ʣ

    View Slide

  87. ͦͷଞ
    • process manager͸ແ͍ͷͰɺӡ༻ʹ͸ผ్
    systemd,supervisord,daemontoolsͳͲΛ࢖͏
    • Α͘΋ѱ͘΋γϯϓϧ
    • ʮߴ଎ʯͱ͍͏ͷ͸ӕͰ͢ɻC֦ுͷeventͳͲΛ͍Εͯɺಛఆ
    ͷ༻్Ͱɺ஫ҙਂ͔͚͘͹ʮ͸΍͍ࣄ΋͋Δʯͱࢥ͏
    • ΠϕϯτۦಈηʔϑͳίʔυΛॻ͘ͷ͸݁ߏ͍ͨ΁ΜɺಛʹDB
    ઀ଓͱ͔ɻ

    View Slide

  88. aerys
    • https://github.com/amphp/aerys
    • amPHPͰ࣮૷͞Εͨhttpd
    • process manager͕͋Δʂ
    • PSR-7ͳʹͦΕ͏·͍ͷʁ(ಠࣗͷreq,res)
    • ݁ߏ׆ൃ

    View Slide

  89. • Static file serving
    • WebSockets
    • Dynamic app endpoint routing
    • Name-based virtual hosting
    • Full TLS support
    • Customizable GZIP output compression
    • HTTP/2.0 support (pushͳͲ)
    • Middleware hooks

    View Slide

  90. • άϨʔεϑϧϦελʔτ
    • ϓϩηεϚωʔδϟʢϫʔΧ਺มߋͳͲʣ
    • Unix domain sock
    • ࣮ߦϢʔβʔมߋ
    • Ϧόϓϩ
    • ηογϣϯʢRedisʣɺCookie
    • ͔ͳΓϓϩμΫγϣϯϨσΟײ͋ΔʢݸਓͷײͰ͢ʣ

    View Slide

  91. use Aerys\{ Host, Request, Response, Websocket,
    function root, function router, function websocket };
    $router = router()
    ->route("GET", "/", function(Request $req, Response $res) {
    $res->end("Hello, world.");
    });
    $root = root($docrootPath = __DIR__);// static file serving
    $fallback = function(Request $req, Response $res) {
    $res->end("Fallback \o/");
    };
    return (new Host)->expose("*", 1337)->use($router)->use($root)->use($fallback);

    View Slide

  92. swoole
    • https://github.com/swoole/swoole-src
    • จ۟ͳ͠ʢʁʣͷproduction readyʂʢςϯηϯτ͕࣮༻͠
    ͍ͯΔʣ
    • high performance for PHP.
    • த՚+C֦ுύϫʔͰ̎̌̌ສഅྗʢʁʣ
    • ͪΌΜͱߋ৽͞ΕͯΔʂ͍͢͝ʂʂ

    View Slide

  93. • ӳޠυΩϡϝϯτ͔ͳΓ੔උ͞Εͨʢͪΐͬͱલ·Ͱதࠃޠ͹
    ͔Γͩͬͨʣ
    • Linux,OSX,WindowsͰ΋ಈ͘ʢͱॻ͍ͯ͋Δ͕ͪΐ͍ඍົʣ
    • Ϗϧυ͸ָʢґଘ͕ͳ͍ʣ
    • IDE helper΋͋Δ

    View Slide

  94. ׬શʹ༨ஊͳSwooleͷ͍͢͝ͱ͜Ζ
    • ͳΜͱʂʂʂPHPͳͷʹʂʂʂCoroutineͱChan(nelʣ͕͋
    ΔʂʂʂGo͔Αʂʂʂ

    View Slide

  95. $chan = new Channel(1024 * 256);
    co::create(function () use ($chan){
    while(1){
    co::sleep(0.5);
    $chan->push("A");
    }
    });
    co::create(function () use ($chan) {
    while(1){
    $ret = $chan->pop();
    if(!$ret){
    co::sleep(0.1);
    continue;
    }
    echo $ret;
    }
    });

    View Slide

  96. • ͳ͓ɺOSXͩͱڍಈ͕͓͔͔ͬͨ͠ɻ·ΕʹηάΔɺsleep͕
    ࢭ·Δɺcoroutine͕ฒ૸͠ͳ͍ɻ
    • ʢͨΊͨ͠ͷ͕ͪΐͬͱલͳͷͰ΋͏࣏ͬͯΔ͔΋ʣ
    • LinuxͩͱͪΌΜͱ͏͘͝งғؾ
    • ඇಉظ͚ͩͰ͸ͳ͍ɺϚϧνεϨουϚϧνϓϩηεͰ࢖͑Δ
    ϩοΫ΍mmapɺ҆શͳϩʔΧϧredisΈ͍ͨͳtableɺϓϩη
    εϚωʔδϟ΋͋Γ…ຊՈʹऔΓࠐ·Εͯ͘Εʂʂʂʂ
    • ਖ਼௚ɺ֦ு͞Ε͗͢Ͱ͸

    View Slide

  97. • HHVMͱ͕ͪ͏ํ޲ੑͰʢPHPͷ··ʢʁʣͰʣਐԽ͍ͤͯͬ͞
    ͍ͯΔΑ͏ʹΈ͑ͯɺݸਓతʹ͸޷ײ͕͋Δ
    • ΈΜͳ͓ࠔΓʹͳΔDNSϦκϧόʢͷඇಉظͷ΍ͭʣ·Ͱ૷උ
    • ʮPHPʹcoroutinͳ͍΍Ζʯʮͤ΍ͳʯ
    • ࣮ࡍ݁ߏߴ଎ͩ͠ɺເͱϩϚϯ͕͍͢͝

    View Slide

  98. ͜ΕͰؾܰʹwaitΛ͔͚Δ͜ͱ΋Ͱ͖Δ͠ɺདྷ೥ͷISUCON͸͜Ε
    ͩʂʢҧ
    ʢISUCON༑ୡืू͍ͯ͠·͢ʣ

    View Slide

  99. ΍ͬͨʂ͜ΕͰ͍͚Δʂʂ
    • C֦ுͳΜͩΑͳ͋…
    • ʮʢ͜͜Ͱ͍͏ʣେ౷Ұײʯ͸ബ͍ʢผʹ౷Ұ͠ͳ͍͍͚ͯ͘
    Ͳʣ

    View Slide

  100. ࠶ܝʣଞͷݴޠ͸ɺC֦ு͸ʮlibʯଆ
    ʹೖΔ
    • phpͩͱɺΠϯετʔϧͨ͠phpͷԼͷmodulesʹ͸͍Δ
    • php.iniʹextensions=hoge.so
    • Ͱ΋·͋ɺdlؔ਺΍࣮ߦ࣌Ҿ਺͔ͭ͑͹͍͍ΜͩΑͶʂ
    • ͱ͍͏͜ͱͰɺಥવͰ͕͢ʮ΄͔ͷݴޠͷC֦ுͷී௨ʯΛճऩ
    ͢Δ͜ͱ͕Ͱ͖·ͨ͠Ͷɺʢಥવͷճऩʣ

    View Slide

  101. ʢISUCON஥ؒืूதͰ
    ͔͢ΒͶʁʣ

    View Slide

  102. ͜͜·Ͱ༨ஊ

    View Slide

  103. ͸͍

    View Slide

  104. ࢲʮͲ͏Ͱ͔͢ʁhttpdʹͳΓ·ͨ͠Αʯ
    ʁʮϑΝΠϧ͕ͨ͘͞Μ͋Δͷ͕ͳ͋…ʯ
    ࢲʮͳΜͩͱʯ

    View Slide

  105. ̍ϑΝΠϧʹ͠ͳ͚Ε͹ʢ࢖໋ײʣ
    • ΍ͬͨΔ͔ʂ

    View Slide

  106. ౷Ұ͍ͯͧ͘͠ʂ

    View Slide

  107. Phar
    • PHPͷίʔυ΍σʔλΛύοΫͰ͖Δ΋ͷ
    • composer.phar͸͝ଘ஌Ͱ͠ΐ͏
    • file_get_contents΍fopenʹphar://ʙΛ౉͢ͱத͕ݟΕ
    Δ
    • stubʹmainతͳ΋ͷΛηοτ͢Ε͹ɺpharϑΝΠϧΛ௚઀
    phpͰ࣮ߦͰ͖Δ
    • php hoge.phar

    View Slide

  108. pharͷ࡞Γํ
    • boxΛ͔ͭ͏ͱ௒؆୯
    • https://github.com/box-project/box2
    • ʮpharΛͭ͘Δͷ͸໘౗ͳͷΛղܾ܅ʯ
    • box.jsonΛॻ͚ͩ͘ʂ
    • ͪΌΜͱComposerͰ͍Εͨ΋ͷ΋ಈ͘

    View Slide

  109. ͱΓ͋͑ͣɺ͖ͬ͞ͷ
    reactPHPͰ࡞ͬͯΈΔ

    View Slide

  110. box.json
    {
    "directories": ["htdocs","lib","templates","vendor"],
    "files": ["config.php","main.php"],
    "main": "main.php",
    "output": "react_tinitter.phar",
    "stub": true
    }

    View Slide

  111. $ php -d phar.readonly=false ~/bin/box.phar build
    Building...
    • -d phar.readonly=false͸σϑΥϧτͰ͸Pharͷʮॻ͖ࠐ
    Έʯ͸ېࢭ͞Ε͍ͯΔͷͰࢦఆɻphp.iniͰ΋͍͍͚Ͳͬͪ͜
    ͷ΄͏͕ૣ͍ΑͶ

    View Slide

  112. • ͔ͳΓ͔͔࣌ؒΓ·͢
    $ time php -d phar.readonly=false ~/bin/box.phar build
    Building...
    real 4m13.202s
    user 1m51.980s
    sys 1m44.934s

    View Slide

  113. real 4m13.202s

    View Slide

  114. • ʮ…͖ͬͱxdebug͕͸͍ͬͯΔ͔Βͩ…ʯ
    • ʮ֦ுΛɺ-dͰ௥Ճ͸Ͱ͖Δ͕ɺ࣮ߦ࣌ʹ࡟আ͸…ʯ
    • ʮ….gitҎԼ·ͰύοΫ͞Εͯͳ͍͔͜Εʁʁʯ

    View Slide

  115. ͔͠͠ɺੈք͸autoload͚ͩͰ͸ͳ
    ͍
    • ex: ςϯϓϨʔτϑΝΠϧɺίϯϑΟά
    • (Tinitterͷ৔߹͸sqlite΋)

    PHP Warning: file_get_contents(public/index.html): failed to open stream:
    No such file or directory in phar:///tmp/example.phar/bin/main on line 26

    View Slide

  116. Phar::interceptFileFuncs();
    • ࠷ߴؔ਺file_get_contents΍fopenͳͲΛԣऔΓ͠·͢
    • ͕͢͞C֦ுɺͦ͜ʹγϏΕΔಌΕΔ
    • /Ͱ࢝·Βͳ͍ʢ૬ରύεʣ৔߹ɺݱࡏͷPhar಺͔ΒಡΉ
    • __DIR__΋͔ͭ͑Δ(phar:///tmp/example.phar/bin)
    • ʮେମʯͳΜͱ͔ಈͧ͘ɻ
    • reactͷ੩తϑΝΠϧ഑৴ΞυΦϯ΋ಈ͘

    View Slide

  117. ͔͠͠PDO͕͏͔͝ͳ͍
    $ php react_tinitter.phar
    Slim Application Error:
    Type: PDOException
    Code: 14
    Message: SQLSTATE[HY000] [14] unable to open database file

    View Slide

  118. Phar::mount()
    • Phar֎ͷϑΝΠϧ΍σΟϨΫτϦΛ͔͋ͨ΋Phar಺ʹ͋Δ͔ͷ
    Α͏ʹࢀর͢Δ͜ͱ͕Ͱ͖Δʢલड़ͱ૊Έ߹ΘͤΔࣄʹͳΔʣ
    • ྫɿpharͷ֎ʹ͋Δsqlite.dbΛɺதʹ͋ΔΑ͏ʹ͢Δ
    Phar::mount(
    'sqlite.db',
    dirname(Phar::running(false)).'/sqlite.db'
    );

    View Slide

  119. • ͜ͷ࣌ɺ__DIR__͕Phar಺෦ʹ͔Θͬͯ͠·͏ͷͰ஫ҙ
    • Α͘΍ΔPDO("sqlite:".__DIR__."/sqlite.db")Έ͍ͨ
    ͳͷ͸ɺ૬ର౳ʹॻ͖׵͑·͠ΐ͏

    View Slide

  120. Phar::running()
    • Pharʹ͠ͳ͍ͱಈ͔ͳ͍ͱ͔ແཧͳͷͰɺPharԽ͞Ε͍ͯΔ͔
    ൱͔Λ஌ΔͨΊʹ͔ͭ͏
    • __FILE__ Έ͍ͨͳ΋ͷ͕ฦ͞ΕΔɺ֎ͳΒfalse
    • Ҿ਺ʹfalseͰɺPharࣗମͷύεΛฦ͢
    $isUnderPhar = (Phar::running()!=="") ;

    View Slide

  121. ͱ͍͏͜ͱͰ
    • ϒʔτετϥοϓʹͳΔmain.phpͷઌ಄ʹॻ͘
    if(Phar::running()!==""){ // under phar
    Phar::mount('sqlite.db', dirname(Phar::running(false)).'/sqlite.db');
    Phar::interceptFileFuncs();
    }
    require "vendor/autoload.php";
    // ...

    View Slide

  122. Ͱ͖ͨʂ
    • DEMO
    • ͯ͠΋ɺผʹ୅ΘΓө͑͠ͳ͍͔Βͳ…

    View Slide

  123. ίʔυ͕େ౷ҰͰ͖ͨʂ

    View Slide

  124. ͸͍

    View Slide

  125. ࢲɿʮ͜ΕͰ̍ϑΝΠϧʹͳͬͨʂʯ
    ʁɿʮ͑ͬɺίʔυͱόΠφϦͱผ͡ΌΜʯ
    ࢲɿʢ΋͸΍ͦΕ͸೉บͳͷͰ͸ʁʁʁʁʣ

    View Slide

  126. சੜɺ͞Βʹ౷Ұͩʂʂ
    • ͱ͍͏͜ͱͰͭͳ͍͖͛ͯ·͠ΐ͏

    View Slide

  127. ग़མͪʣ΍ͬͨʂେ౷Ұͩʂʂ
    $ cat /usr/bin/php main.php > one-pack-php
    $ ./one-pack-php -r \
    "eval('?>'.substr(file_get_contents('one-pack-php'),
    strlen(file_get_contents('/usr/bin/php'))));"
    • ̍ϑΝΠϧʹόΠφϦͱPHP͕͸͍ͬͨͧʂʂ

    View Slide

  128. ղઆ
    cat php main.php > one-pack-php
    !
    [PHPόΠφϦ] + [PHPίʔυ] = [PHPόΠφϦ|PHPίʔυ]

    View Slide

  129. $ ./one-pack-php \ # ͭͳ͛ͨPHP
    -r \ # Ҿ਺ͰPHPίʔυࢦఆɺҎԼPHPίʔυ
    "eval('?>'. // 'substr( // όΠφϦ෼ɺಡΈඈ͹͢
    file_get_contents('one-pack-php'), // ͭͳ͛ͨPHPΛಡΈࠐΉ
    strlen( // ಡΈඈ͹͢௕͞ΛܾΊΔɺ͜͜͸ຊ౰͸਺஋ʹॻ͖׵͑Δ
    file_get_contents('/usr/bin/php')) // ඈ͹͢௕͞
    )
    );"
    !
    [PHPόΠφϦ|PHPίʔυ]
    ^~~͜͜·ͰεΩοϓͯ͠ɺ
    ͦΕΛeval͍ͯ͠Δ

    View Slide

  130. ʮ΍ͬͨͥʂ౷Ұͩʂʯ

    View Slide

  131. օ͞Μͷײ૝
    • ʮ͏ͦͩΖʂʁʯ
    • ʮ͏ͦͰ͸ͳ͍ʯ

    View Slide

  132. օ͞Μͷײ૝̎
    • ʮਖ਼ؾͷࠫଡͰ͸ͳ͍ʯ
    • ʮ͔ͨ͠ʹʯ

    View Slide

  133. ී௨ͷͨΊʹ͸ඇৗࣝΛ͠ͳ͚Ε͹…ʢʣ

    View Slide

  134. ΍ͬͨʂ͜ΕͰউརʂʂ
    • ͱ͓΋͍͍͕ͨ…

    View Slide

  135. ͨΜͳΔPHPιʔεͳΒಈ͕͘…
    • phar͸fsʹ͓͔Ε͍ͯͳ͍ͱopenͰ͖ͳ͍
    • ʢphp ext/pharͷιʔεΛΈΔͱ…ʣ
    • ͙͙͙

    View Slide

  136. ͦͷ͜Ζࢲ͸
    YAPC::Okinawaͷҝɺ
    ԭೄʹ͍ͨ

    View Slide

  137. • ʮ…͏ͬ͢Βؾ͍͍͕ͮͯͨɺ͜Ε͸ແཧͳͷͰ͸…ʯ
    • (ԭೄ໊෺ίʔώʔ๐੝ΛҿΉ)
    • ʮ͍ͬͯ͏͔ɺfs͕ͳ͍؀ڥͳ͍΍Ζɺfs͔͓ͭ͏ʯ

    View Slide

  138. • ͱ͍͏͜ͱͰਖ਼ؾʹͳΓPharͱPHP࿈݁Ҋ͸ϘπʹͳΓ·ͨ͠
    • ʢʮ౷Ұʯͷֶͼ͸͋ͬͨʣ
    • ʢ؇ืɿΑ͍ಀ͛ಓʣ

    View Slide

  139. ୅Ҋ bash ࣗݾղౚʹΑΔ࣮ߦ
    • ͪ͜Β͸ඇৗʹ༝ॹਖ਼͍͠खஈͰ͢Ͷ
    • php, codeΛղౚ࣮ͯ͠ߦ

    View Slide

  140. #!/bin/bash
    # head.sh
    function finish () {
    cd -
    rm -rf $RUNPACKDIR
    exit
    }
    RUNPACKDIR=`mktemp -d /tmp/runpackphp.XXXXX`
    trap 'finish' {1,2,3,15}
    ENDLINE=$(grep --line-number --text "^##ENDLINE$" $0 | sed 's/:.*//')
    : $((ENDLINE++))
    tail -n +$ENDLINE $0 | tar xzf - --directory $RUNPACKDIR
    cd $RUNPACKDIR
    $RUNPACKDIR/php $RUNPACKDIR/main.php
    cd -
    exit
    ##ENDLINE

    View Slide

  141. #!/bin/sh
    # build.sh
    cd ../
    tar czf --exclude-vcs selfbash/ball.tgz \
    htdocs lib templates vendor \
    sqlite.db main.php config.php php
    cd -
    cat head.sh ball.tgz > selfbash.sh
    chmod +x selfbash.sh

    View Slide

  142. Ͱ͖ͨʂ
    • demo

    View Slide

  143. ΋͠࢖͏ةಞͳਓ΁ͷ஫ҙ
    • ্ͷίʔυͷtar͸gnu tarͰ͢ɺosxͰ΍ΔͳΒbrewͰ͍Ε
    ΔͳΓ͍ͯͩ͘͠͞
    • ʢ͋Δ͋Δ…ʣ
    • sqlite.db·ͰಥͬࠐΉͱɺ౰વ࠶ىಈͷͨͼʹר͖໭Γ·
    ͢ɻMysqlͱ͔࢖͍ͬͯͩ͘͞ɻ

    View Slide

  144. ʮ͍ͭʹʂେ౷Ұʂͩʂʯ

    View Slide

  145. ͸͍

    View Slide

  146. ࢲɿʮ͜ΕͰͲ͏Ͱ͔͢ʂʯ
    ʁɿʮ͍ͬͯ͏͔ɺPHP͸Dockerͱ͔ʹͯ͠΋ΠϝʔδαΠζͰ
    ͔͗͢ΔΘɺPHP͸͜Ε͔ͩΒʯ
    • ʢ͍ͬͯ͏͔͖ͬ͞ͷͰಥવPHP͕ϫϯόΠφϦͰίϐʔͯ͠Δ
    ॴ͕෍ੴͰ͢Ͷʣ

    View Slide

  147. சੜখͯ͘͞͠΍Δʂʂ
    • ੎͍Ͱɺ̍όΠφϦͰɺখ͍͞PHPΛͭ͘Δ
    • ʢಥવͷϧʔϧɿҰݸͷϑΝΠϧͰ·ͬ͞Βͳ؀ڥʹ΋͍ͬͯ
    ͬͯ͏͚͝͹OKʣ

    View Slide

  148. ઌऔΓΦν৘ใ
    $ ./configure --disable-all --enable-mbstring --enable-json
    $ make all
    $ cp sapi/cli/php /path/to/php

    View Slide

  149. Ͱ͖ͨʂʂ
    • ʮMac΍LinuxͰ͸͍͚ͨΑʂʯ
    • ʮ͍΍…Զ͸Docker͔ͩΒ…ʯ
    • ʮνοʯ

    View Slide

  150. alpineͰಈ͘࠷খͷPHPΛ࡞͍ͬͯ͘
    • ຌ༱ʹUbuntuͩͱ1GB͘Β͍͋Δɺ͔ͨ͠ʹ͖ͼ͍͠
    • ެࣜϨγϐͩͱ60Mbyte͘Β͍
    • ͑ͬɺ͜ΕͰσΧΠͷʁ

    View Slide

  151. Φν ʢ7.2.2ͷྫͰ͢ʣ
    ./configure \
    --disable-cgi --without-pear \
    --enable-ftp --enable-mbstring --enable-mysqlnd \
    --with-openssl --with-zlib \
    --disable-libxml --disable-dom --disable-xml \
    --disable-simplexml --disable-xmlreader --disable-xmlwriter
    • ެࣜͷDockerFileΛվ଄͢Δͱָ
    • όΠφϦΛ͵͍ͯɺૉͷ΋ͷʹίϐʔ͔ͯͭ͠͏
    • SSL͸࠷ॳ͔Β͋Δɺlibxml͕Ͱ͔͍ΜͩΑͳ͋…

    View Slide

  152. ݁Ռ
    $ docker image list
    REPOSITORY TAG IMAGE ID CREATED SIZE
    miniphp latest fa69ea70ab4c 2 weeks ago 11.4MB
    php-7.2.2-cli-alpine3.7 1.0 0a93147b91ab 2 weeks ago 62.5MB

    View Slide

  153. miniphp 11.4MB
    php-7.2.2-cli-alpine3.7 62.5MB
    • ʮ11Mbyteͩͧɺ΋͏ΏΔͯ͘͠Ε…ʯ

    View Slide

  154. ͨͩɺ๻͸ผʹDockerΛ͔ͭΘͳ͍ͷͰ
    • ࣮ࡍʹ͜Μͳ͜ͱΛීஈ͸͠ͳ͍
    • ͱΓ͋͑ͣ࡞ͬͨΜͩ

    View Slide

  155. ʢ͜ͷ݁Ռ͸·ͩ΋͍ͬͯͬͯͳ͍ͷͰɺଓ͖͕͋Δ͔͸Θ͔Γ·
    ͤΜʣ

    View Slide

  156. ͱ͍͏͜ͱͰɺ
    • PHP͕httpdʹͳΔΑ͏ʹͯ͠
    • PHPΛϫϯόΠφϦʹͯ͠
    • ࣗݾղౚܗࣜͰύοΫͯ͠
    • ̍ϑΝΠϧʹ͢Δ͜ͱʹΑΓ
    • ଞͷݴޠͷਓ͕͍͏ʢʁʣʮී௨ʯͬΆ͍ʢಠࣗݟղʣφχΧ
    ͕Ͱ͖ͨ

    View Slide

  157. ʮ͜Ε͕ϫΠͷେ౷Ұ΍ʂʯ

    View Slide

  158. !
    • ·ͱΊʹೖ͍͖ͬͯ·͢

    View Slide

  159. ·ͱΊ
    • ແ೉ʹapache+mod_phpɺ͋Δ͍͸nginx+php-fpmΛ࢖͍·
    ͠ΐ͏
    • ͦΕͰ΋νϟϨϯδ͢Δਓɺͥͻ๻ͱ͓࿩͠·͠ΐ͏
    • ʮདྷ೥͋ͨΓͷISUCONʹSwooleͰग़Δ༑ୡΛืू͍ͯ͠·
    ͢ʂʯ

    View Slide

  160. ʮԶ͸઴࢝͘Ίͨ͹͔Γ͔ͩΒͳɹ
    ɹ͜ͷ͸ͯ͠ͳ͘ԕ͍େ౷ҰΛΑ…ʯ
    (to be continued...)
    (࣭໰Ͳ͏ͧ)
    (ͳ͚Ε͹༨ஊ)

    View Slide