{
    "componentChunkName": "component---src-templates-blog-post-jsx",
    "path": "/post/how-to-implement-framework-with-php-in-5-minutes/",
    "result": {"data":{"site":{"siteMetadata":{"title":"WEB EGG","author":"Leko - CTO at Yuimedi"}},"markdownRemark":{"id":"e28e15ce-ef63-5a75-a082-4eb743c44b02","excerpt":"こんにちは。 突然ですが、PHPのフレームワークを作ろうと思います。 大層なタイトルを掲げてしまいましたが、制作自体は全く5分ではありません。けっこう時間かかりました じっくり時間を書けて調査した結果、記事に倣って書けば5分くらいで完成する、という意味での…","html":"<p>こんにちは。<br>\n突然ですが、PHPのフレームワークを作ろうと思います。</p>\n<p>大層なタイトルを掲げてしまいましたが、制作自体は全く5分ではありません。けっこう時間かかりました<br>\nじっくり時間を書けて調査した結果、記事に倣って書けば5分くらいで完成する、という意味での5分です</p>\n<p>記事は２本立ての構成で、今回は技術選定・設計編です。</p>\n<!--more-->\n<h2 id=\"完成品\" style=\"position:relative;\"><a href=\"#%E5%AE%8C%E6%88%90%E5%93%81\" aria-label=\"完成品 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>完成品</h2>\n<ul>\n<li><a href=\"https://github.com/Leko/rush\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Githubのリポジトリ</a></li>\n<li><a href=\"https://rushframework.herokuapp.com\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">公式ページ</a></li>\n</ul>\n<p>↑を作っていく過程を記事に残します。</p>\n<h2 id=\"この記事の目的\" style=\"position:relative;\"><a href=\"#%E3%81%93%E3%81%AE%E8%A8%98%E4%BA%8B%E3%81%AE%E7%9B%AE%E7%9A%84\" aria-label=\"この記事の目的 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>この記事の目的</h2>\n<ul>\n<li>PSRの可能性、ありがたみを感じてもらう</li>\n<li>ピンポイントながらいい感じのライブラリを紹介する</li>\n<li>フレームワークをブラックボックスではなく「ただのPHPコード」として身近に感じる</li>\n</ul>\n<p>数年前から動いている<a href=\"http://www.php-fig.org/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">PHP-fig</a>という団体が提唱するPSRという仕様のうち、<a href=\"http://www.php-fig.org/psr/psr-6/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">6(Caching Interface)</a>、<a href=\"http://www.php-fig.org/psr/psr-7/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">7(HTTP Message Interface)</a>の登場に、衝撃が走りました<br>\n<strong>これはPHPのフレームワークもライブラリも変わるぞ</strong> 、と<br>\n特にPSR-7が強力で、 <em>HTTPミドルウェア</em> という概念が、フレームワーク依存のオレオレ仕様ではなくやっと標準的な形になったと言えます</p>\n<p>PSR7の登場により、ほんの1~2年前くらいに誕生した比較的新しいフレームワークですら、 <strong>PSR-7に追従していなければもはやレガシー</strong> と言っても過言ではないと思います<br>\nそんな変化の激しい世界ですが、流行り廃りに依らない記事が書ければと思っております</p>\n<p>この記事を書くに至ったきっかけのもう一つが、「PSR登場以後に流行ってるライブラリ」を全く追っていなかったので、<br>\n私自身の知見をアップデートするいい機会だなと思ったことが挙げられます</p>\n<p>また、明示的に記事のコンテンツにはしませんが、裏目的として「フレームワークはただのPHPコードの塊だ」と感じてもらうことも狙っています<br>\n小さなパーツを組み上げていくことで、ブラックボックスなものではなく「ただのPHPじゃん」と身近に感じてもらいたいと思っています</p>\n<p>なお、今回の記事ではOSSコミュニティやグロースなどはスコープ外とし、<br>\n単にPHPのコードやWAFといった仕様や技術的な箇所について書きます。</p>\n<h2 id=\"名前を決める\" style=\"position:relative;\"><a href=\"#%E5%90%8D%E5%89%8D%E3%82%92%E6%B1%BA%E3%82%81%E3%82%8B\" aria-label=\"名前を決める permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>名前を決める</h2>\n<p>フレームワークの名前は <strong>Rush</strong> にしました<br>\n被ってなくて、言いやすくて、読みが明確で、短くて、覚えやすくて、さり気なく意味がこもっている名前です<br>\n<a href=\"http://ejje.weblio.jp/content/rush+job\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Rush job</a>（突貫工事、やっつけ仕事）から取っています</p>\n<p>あまり良い意味の名前ではないですが、5分というテーマを掲げるならちょうど良い自嘲かなと思います</p>\n<h2 id=\"インスパイア元\" style=\"position:relative;\"><a href=\"#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%91%E3%82%A4%E3%82%A2%E5%85%83\" aria-label=\"インスパイア元 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>インスパイア元</h2>\n<p><a href=\"http://adonisjs.com/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Adonis</a>というNodejsのフレームワークと、<br>\n<a href=\"http://www.slimframework.com/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Slim v3</a>にインスパイアされています</p>\n<p>ちなみにAdonisはLaravelにインスパイアされています</p>\n<h2 id=\"欲しい要件要素の洗い出し\" style=\"position:relative;\"><a href=\"#%E6%AC%B2%E3%81%97%E3%81%84%E8%A6%81%E4%BB%B6%E8%A6%81%E7%B4%A0%E3%81%AE%E6%B4%97%E3%81%84%E5%87%BA%E3%81%97\" aria-label=\"欲しい要件要素の洗い出し permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>欲しい要件・要素の洗い出し</h2>\n<ul>\n<li>実装は最小限。ニーズを満たせない所だけ作る</li>\n<li>PHP 5.5以上対応</li>\n<li>HTTPリクエスト/レスポンスはPSR7準拠</li>\n<li>ルーティング</li>\n<li>HTTPミドルウェア</li>\n<li>DB操作のモデル</li>\n<li>DIコンテナ</li>\n<li>テンプレートエンジン</li>\n<li>設定ファイルを扱う仕組み</li>\n<li>ファイルパス操作</li>\n<li>フロントエンドは色々な構成がありすぎるので何も手を入れない</li>\n</ul>\n<h3 id=\"phpのバージョン\" style=\"position:relative;\"><a href=\"#php%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3\" aria-label=\"phpのバージョン permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>PHPのバージョン</h3>\n<p><a href=\"http://php.net/supported-versions.php\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">PHPのサポート状況</a>から対応すべきバージョンを決定しました<br>\nPHP 5.4のサポートってすでに終了していたんですね。 <del>知りませんでした</del></p>\n<h3 id=\"ルーティング\" style=\"position:relative;\"><a href=\"#%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0\" aria-label=\"ルーティング permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>ルーティング</h3>\n<p><a href=\"https://github.com/thephpleague/route\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">thephpleague/route</a>ではなく<a href=\"https://github.com/nikic/FastRoute\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">nikic/FastRoute</a>を採用 thephpleague/routeのPSR-7対応版は<a href=\"https://github.com/thephpleague/route/pull/73\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">まだrc</a>なので、時期尚早だと判断した</p>\n<h3 id=\"httpリクエストレスポンスはpsr7準拠\" style=\"position:relative;\"><a href=\"#http%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9%E3%81%AFpsr7%E6%BA%96%E6%8B%A0\" aria-label=\"httpリクエストレスポンスはpsr7準拠 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>HTTPリクエスト/レスポンスはPSR7準拠</h3>\n<p><a href=\"https://github.com/zendframework/zend-diactoros\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">zend-diactoros</a>を採用<br>\n他にいい感じのライブラリがなかったのと、古に伝わりしZendブランドがPSRとか標準化に貢献していることに好感を感じるので採用しました</p>\n<p>ブラウザにレスポンスを返す処理が見当たらなかったので、<a href=\"https://github.com/slimphp/Slim/blob/3.x/Slim/App.php#L354\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Slimのコード</a>からそのまんまな処理をパクってきます。</p>\n<h3 id=\"httpミドルウェア\" style=\"position:relative;\"><a href=\"#http%E3%83%9F%E3%83%89%E3%83%AB%E3%82%A6%E3%82%A7%E3%82%A2\" aria-label=\"httpミドルウェア permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>HTTPミドルウェア</h3>\n<p><a href=\"https://github.com/oscarotero/psr7-middlewares\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">oscarotero/psr7-middlewares</a>を採用<br>\nSlimと互換性があることと、色々種類が揃っているため便利そうなので採用しました<br>\n色々な種類のミドルウェアが入っているので、実装者が取捨選択する感じにしようと思います。</p>\n<p>強いてあげるなら<a href=\"http://php.net/manual/ja/language.generators.overview.php\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Generator</a>を使用して第三引数がなくなると、よりシンプルだなと思います<br>\nしかしPHPはほぼ全てが同期APIなので、Nodejs(Adonis)のような必然性、メリットが特にないため流行る将来が見えません。<br>\nということでジェネレータ非対応ですがこのライブラリを採用します。</p>\n<ul>\n<li>採用する\n<ul>\n<li>これらのミドルウェアはフレームワーク内に組み込みます。<br>\nとはいえ依存しているのはルーティングくらいなのであとは取捨選択できます</li>\n<li><a href=\"https://github.com/oscarotero/psr7-middlewares#fastroute\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">FastRoute</a>\n<ul>\n<li>ルーティングで採用しているFastRouteのミドルウェアがありました。ルーティングはHTTPミドルウェアの1つとして動作させます</li>\n</ul>\n</li>\n<li><a href=\"https://github.com/oscarotero/psr7-middlewares#clientip\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ClientIp</a>\n<ul>\n<li>主な想定はHerokuですが、PHPなら自前で組むとしてもFastCGIサーバが手前に噛む構成が多いと思います。そんな時にも使いやすいミドルウェアです</li>\n<li>ちなみにHerokuの場合だと以下のヘッダがアプリケーションサーバへ渡ってくるそうです。 <a href=\"https://devcenter.heroku.com/articles/http-routing\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">参照</a>\n<ul>\n<li><code>X-Forwarded-For</code>: the originating IP address of the client connecting to the Heroku router</li>\n<li><code>X-Forwarded-Proto</code>: the originating protocol of the HTTP request (example: https)</li>\n<li><code>X-Forwarded-Port</code>: the originating port of the HTTP request (example: 443)</li>\n<li><code>X-Request-Start</code>: unix タイムスタンプ (milliseconds) when the request was received by the router</li>\n<li><code>X-Request-Id</code>: the Heroku HTTP Request ID</li>\n<li><code>Via</code>: a code name for the Heroku router</li>\n</ul>\n</li>\n</ul>\n</li>\n<li><a href=\"https://github.com/oscarotero/psr7-middlewares#csrf\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Csrf</a>\n<ul>\n<li>言わずもがなCSRFプロテクションです</li>\n<li>アプリケーションの仕様上これを入れることにで都合が悪くなることもあるので、付け外し出来る前提で組み込みます</li>\n</ul>\n</li>\n<li><a href=\"https://github.com/oscarotero/psr7-middlewares#languagenegotiation\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">LanguageNegotiation</a>\n<ul>\n<li>多言語化の文言管理、取得の仕組み自体は色々有りますが、 <em>何の言語で表示したら良いのか</em> は地味に面倒で、かつついオレオレ仕様で書いてしまいがちです</li>\n<li>PHPのドキュメントのように言語情報をパスに込めることも可能です</li>\n<li>原則はHTTPの仕様通り、最悪Cookieで上書きできる、という形で組み込もうと思います</li>\n</ul>\n</li>\n<li><a href=\"https://github.com/oscarotero/psr7-middlewares#errorhandler\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ErrorHandler</a>\n<ul>\n<li>エラーハンドリングもミドルウェアとして提供されています。 <strong>その手があったか！</strong> と感動したし便利なので採用</li>\n</ul>\n</li>\n<li><a href=\"https://github.com/oscarotero/psr7-middlewares#whoops\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Whoops</a>\n<ul>\n<li>Railsで言うところの<a href=\"https://github.com/charliesome/better_errors\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">better_errors</a>のようなデバッグ用エラー画面です</li>\n<li>開発環境ではこれ使うのが捗るので入れておきます</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>紹介するだけ\n<ul>\n<li>これらのミドルウェアは便利そうなのですが入れると余計なロックインが起きそうだったので見送りました。紹介までにとどめます</li>\n<li><a href=\"https://github.com/oscarotero/psr7-middlewares#csp\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Csp</a>\n<ul>\n<li><a href=\"https://developer.mozilla.org/ja/docs/Web/Security/CSP\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Content Security Policy</a>の設定を提供してくれるミドルウェア</li>\n</ul>\nまだブラウザの対応状況が微妙なのでフレームワークでの採用は見送り。要件や対応ブラウザによっては使えそうです</li>\n<li><a href=\"https://github.com/oscarotero/psr7-middlewares#googleanalytics\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">GoogleAnalytics</a>\n<ul>\n<li>言わずと知れたGoogle Analyticsのトラッキングコードを仕込むミドルウェア</li>\n<li>テンプレート自体が共通化されていればPHPでやることはないので、見送り</li>\n</ul>\n</li>\n<li><a href=\"https://github.com/oscarotero/psr7-middlewares#minify\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Minify</a>\n<ul>\n<li>出力するファイルを圧縮して送信できるミドルウェア</li>\n<li>HTTPミドルウェアの責務ではなくて、静的ファイル(gzipなど)ならWebサーバやビルドツール、動的文字列ならテンプレートエンジンの役割だと思っているため見送り</li>\n</ul>\n</li>\n<li><a href=\"https://github.com/oscarotero/psr7-middlewares#rename\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Rename</a>\n<ul>\n<li>ルーティングの上書きができるミドルウェア</li>\n<li>必要なケースが限定的なので見送り</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"db操作のモデル\" style=\"position:relative;\"><a href=\"#db%E6%93%8D%E4%BD%9C%E3%81%AE%E3%83%A2%E3%83%87%E3%83%AB\" aria-label=\"db操作のモデル permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>DB操作のモデル</h3>\n<p>Laravelの<a href=\"https://github.com/illuminate/database\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Illuminate\\Eloquent</a>を採用しました<br>\nもっともAPIが直感的だと思います。また、Laravelで使用されていることも有り、大規模な構成になっても耐えられそうなため採用しました</p>\n<p>ちなみに内部ではDoctrineが使用されている箇所があります。</p>\n<p>他に検討したライブラリだと、<br>\n<a href=\"https://github.com/fuel/orm\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">fuel/orm</a>や<a href=\"https://github.com/j4mie/idiorm\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">idiorm</a>や<a href=\"https://github.com/j4mie/paris\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">paris</a>、<a href=\"https://github.com/doctrine/doctrine2\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">doctrine/orm</a>はAPIがイケてないと言った感じでした</p>\n<h3 id=\"diコンテナ\" style=\"position:relative;\"><a href=\"#di%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A\" aria-label=\"diコンテナ permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>DIコンテナ</h3>\n<p>phpdiを採用しました。</p>\n<p>複雑なビジネスロジックを組んでいるとテストできないような膨大な化物ができあがってしまうことが良くあります<br>\n焼け石に水で、そもそも論はいくらでも言えますが、 <strong>明示的に意識させ、化物を産まれくくできる</strong> 点で、実装者のスキル差を軽減できるパターンの一つだと思います<br>\nモックをさらっと当ててテストが出来る点は一度覚えてしまうとやめられない快感です</p>\n<p>そんな訳でDIコンテナの仕組みは入れておきたいです。でもSymfonyほど大袈裟なものは要らない<br>\nどれを採用するかとても迷いました。Githubでの人気具合だと</p>\n<ul>\n<li><a href=\"https://github.com/silexphp/Pimple\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Pimple</a>: スター数 1225\n<ul>\n<li>人気だけど連想配列っぽく扱うのがあまり好きではない。こんな記事もあったり<br>\n<a href=\"http://gonzalo123.com/2012/09/03/dependency-injection-containers-with-php-when-pimple-is-not-enough/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Dependency Injection Containers with PHP. When Pimple is not enough.</a></li>\n</ul>\n</li>\n<li><a href=\"https://github.com/PHP-DI/PHP-DI\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">phpdi</a>: スター数 658</li>\n<li><a href=\"https://github.com/auraphp/Aura.Di\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Aura.DI</a>: スター数 213</li>\n</ul>\n<p>という感じでした<br>\n中くらいの人気度、コードベースでなく設定ベースなところからphpdiを採用します</p>\n<blockquote>\n<p>蛇足。悩んだのでSlimを調べてみたところ、<a href=\"https://github.com/container-interop/container-interop\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">container-interop/container-interop</a><br>\nというライブラリが使われていました。幅広く抽象的なインタフェースだと思います。要メモ</p>\n</blockquote>\n<h3 id=\"テンプレートエンジン\" style=\"position:relative;\"><a href=\"#%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%B3\" aria-label=\"テンプレートエンジン permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>テンプレートエンジン</h3>\n<p><strong>自前で実装します。</strong><br>\nといってもテンプレートエンジン自体を実装するのではなく、 <strong>複数のテンプレートエンジンを切り替えられる仕組み</strong> を作ります</p>\n<p>ということで作りました</p>\n<blockquote>\n<p><a href=\"/post/write-interface-of-modern-template-engine-in-php/\">PHPのテンプレートエンジンについて調べて共通インタフェースを作った</a></p>\n</blockquote>\n<h3 id=\"設定ファイルを扱う仕組み\" style=\"position:relative;\"><a href=\"#%E8%A8%AD%E5%AE%9A%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E6%89%B1%E3%81%86%E4%BB%95%E7%B5%84%E3%81%BF\" aria-label=\"設定ファイルを扱う仕組み permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>設定ファイルを扱う仕組み</h3>\n<p>自前で作っても簡単ですが、自前ではなく<a href=\"https://github.com/hassankhan/config\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">hassankhan/config</a>を採用しました</p>\n<p>JSON, YAML, PHP, Iniに対応しているようです<br>\nこういった小さくて抽象的なライブラリ非常に好きです</p>\n<h3 id=\"ファイルパス操作\" style=\"position:relative;\"><a href=\"#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%91%E3%82%B9%E6%93%8D%E4%BD%9C\" aria-label=\"ファイルパス操作 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>ファイルパス操作</h3>\n<p><a href=\"https://github.com/webmozart/path-util\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">webmozart/path-util</a>を採用</p>\n<p>PHP組み込み定数の<code>DIRECTORY_SEPARATOR</code>は名前が長い。長過ぎます<br>\nとはいえFuelPHPのように<code>DS</code>といった略称を作っても仕方ないので、もっと根本的な解決策を探った結果、見つけました</p>\n<p>さらに言えば、PHPのファイル操作関数は命名に統一性がなくバラバラで分かりにくいです<br>\nnodeでいう<a href=\"https://nodejs.org/api/path.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">path</a>モジュールのようなのがほしいな～と探して見つけたのがこのライブラリです</p>\n<p>なんだかんだでファイルパス操作はよく行うので、あらかじめ入れておくとコア層でもアプリ層でもいい感じになるだろう。と見込んで採用しました</p>\n<h2 id=\"ディレクトリ構成\" style=\"position:relative;\"><a href=\"#%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E6%A7%8B%E6%88%90\" aria-label=\"ディレクトリ構成 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>ディレクトリ構成</h2>\n<p>アプリケーションのディレクトリ構成は以下のようにしようと思います。</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">.\n├── bootstrap.php\n├── config\n│   ├── database.php\n│   ├── middlewares.php\n│   ├── providers.php\n│   ├── routes.php\n│   └── view.php\n├── public\n│   └── index.php\n├── resouces\n│   ├── storage\n│   └── views\n└── app\n    ├── Http\n    │   ├── Controller\n    │   └── Middleware\n    └── Model</code></pre></div>\n<p>Adonisを真似ました。このディレクトリ構成気に入っています<br>\nコントローラは居るのか？ という自問自答に対しては、「無名関数はユニットテストしにくい」という結果から採用しました<br>\nコントローラを使わなくても良いので、その辺のお手軽さも柔軟にやれればと思います。</p>\n<h2 id=\"まとめ\" style=\"position:relative;\"><a href=\"#%E3%81%BE%E3%81%A8%E3%82%81\" aria-label=\"まとめ permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>まとめ</h2>\n<p>いかがだったでしょうか。<br>\nこれらのライブラリを組み合わせて、次回実装編でフレームワークを組み上げます。</p>\n<p>この記事の中で、1つでも知らなくて役に立つライブラリが見つかっていれば、してやったりです。</p>","timeToRead":14,"frontmatter":{"title":"5分で作るPHPフレームワーク（技術調査、設計編）","tags":["Framework","Nodejs","PHP","PSR"],"date":"March 14, 2016","featuredImage":null}}},"pageContext":{"slug":"/how-to-implement-framework-with-php-in-5-minutes/","previous":{"fields":{"slug":"/write-interface-of-modern-template-engine-in-php/"},"frontmatter":{"title":"昨今のPHPのテンプレートエンジンについて調べて共通インタフェースを作った","tags":["Github","PHP","Template Engine"]}},"next":{"fields":{"slug":"/learn-of-shebang/"},"frontmatter":{"title":"シバン(shebang)をやっと理解した","tags":["PHP","UNIX"]}}}},
    "staticQueryHashes": ["2585454260","2954598359"]}