tag:blogger.com,1999:blog-9576907519249677352024-03-14T10:38:53.366+09:00仕事SPOTWorkSpot.JP (ワークスポット・ジェーピー)のブログ。<br>
仕事・技術・その他の雑記。asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.comBlogger160125tag:blogger.com,1999:blog-957690751924967735.post-12978920998358785972016-03-16T13:24:00.001+09:002016-03-16T13:24:28.861+09:00Qiitaに投稿「PHPの【クロージャー、クラスのnew、クローン】の比較」Qiitaに投稿しました。<br /><br /><a href="http://qiita.com/asaokamei/items/9630b60dc051a3014a4b">PHPの【クロージャー、クラスのnew、クローン】の比較</a><br />
<br />
最初はクロージャーとクラスのnewでの生成の速度比較だったのですが、クローンを足して、<u>つい関数呼び出しも比較した</u>のが問題だった。<br />
<br />
指摘されてる通り、関数呼び出しは実行時間であり、その他は生成についての速度なので、比較できない。<br />
<br />
にもかかわらず、関数が遅かったので、<b>関数が遅い</b>、と書いてしまった…<br />
しかもタイトルに。<br />
<br />
速度測定は難しい、ということがよく分かりました。<br />
(今は修正済み)<br />
<br />
<h3>
クラスのnewについて</h3>
<br />
さらに言えば、クラスをインスタントする場合で一番時間がかかるのは、コンポーザーのオートローディング。もっと言えばfile_existsでのファイル存在チェック。<br />
<br />
同じクラスを何度もnewするなら同じ速度ですが、実際としてはクロージャーを使うほうが速い場合は多いはず。<br />
<br />
<br />asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-27375977532662966752016-01-16T09:43:00.000+09:002016-01-18T09:44:27.363+09:00Qiita:PSR-7のミドルウェアは、何故ああなのか?」Qiitaに投稿しました。<br />
<br />
<div style="text-align: center;">
<b>「<a href="http://qiita.com/asaokamei/items/b6c83910dcb2256cfaa6">PSR-7のミドルウェアは、何故ああなのか?</a>」</b></div>
<br />
PSR-7でよく見るミドルウェアの引数(シグネチャ)に関する話です。どうして、あの形が使われるのか考えてみました。<br />
<br />
なんというか、LTネタ的な話です。asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com2tag:blogger.com,1999:blog-957690751924967735.post-35251227155641490712016-01-07T09:56:00.000+09:002016-01-07T11:07:06.786+09:002015年を振り返って2(Tuum/Respond開発日誌メモ)<a href="http://wsjp.blogspot.jp/2016/01/2015tuum.html">2015年を振り返って</a>、の続きです。<br />
<br />
昨年の2015年6月から始めたのが<b>「<a href="https://github.com/TuumPHP/Respond">Tuum/Respond</a>」</b>というプロジェクト。開発方針を転換して、PSR-7ベースのマイクロフレームワークに<b>後付でViewの機能を追加するパッケージ</b>を目指しました。<br />
<br />
面白かったのは、開発してゆくにつれ、どんどんコードが簡単になってゆきました。機能を絞ったことで、何をしているか理解できたからと思います。<br />
<br />
いったい何をするのか。<br />
自分で理解した形で説明します。<br />
使い方とかは、Githubのページを見てください。<br />
<br />
要するに次の2つを管理するパッケージです。<br />
<br />
<ul>
<li><b>ViewData</b>: ビューを作るのに必要な情報を運ぶデータ転送オブジェクト。これに必要な情報を設定してゆく。</li>
<li><b>ViewInterface</b>: ViewDataからテンプレートなどでビューを構築して、レスポンスを返すインターフェース。</li>
</ul>
<br />
これだけなのですね。<br />
<br />
<h3>
ViewerInterface</h3>
<br />
Tuum/Respondの肝は、様々な方法でレスポンスオブジェクトを構築すること。<br />
<br />
レスポンスを構築する、ということは、ビューを構築する、とほぼ同じです。ということで、次のインターフェースが出来ました。<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">use Psr\Http\Message\ResponseInterface;<br />use Psr\Http\Message\ServerRequestInterface;<br />use Tuum\Respond\Responder\ViewData;<br />interface PresenterInterface {<br /> /**<br /> * renders $view and returns a new $response.<br /> *<br /> * @param ServerRequestInterface $request<br /> * @param ResponseInterface $response<br /> * @param ViewData $view<br /> * @return ResponseInterface<br /> */<br /> public function render(<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>ServerRequestInterface $request,<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>ResponseInterface $response,<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>$view);<br />}</span></blockquote>
<br />
リクエストとレスポンスのオブジェクト、それとビュー構築に必要なデータの入ったViewDataというオブジェクトを受け取ります。適宜ボディを構築して、レスポンスオブジェクトを返します。<br />
<br />
ついでに同じインターフェースで、ちょっと動きの違うAPIを定義しました。<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">interface ErrorViewInterface extends PresenterInterface {}<br />interface ViewerInterface extends PresenterInterface {}</span></blockquote>
<br />
この3つのインターフェースの使い分けは、<br />
<br />
<br />
<ul>
<li><b>PresenterInterface</b>: <br />$viewを受け取って、レスポンスを返す汎用インターフェース。</li>
<li><b>ViewerInterface</b>: <br />テンプレートからビューを描画することで、レスポンスを返す。</li>
<li><b>ErrorViewInterface</b>: <br />ステータスコードに対応するテンプレートを描画することで、レスポンスを返す。エラー用。</li>
</ul>
<br />
<br />
それぞれのインターフェースを実装したクラスを作っておいて、呼び出します。次のコードを見ると、どれがどのAPIに対応するか、すぐわかると思います。<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Response::view($req)->view('template/filename');<br />Response::error($req)->forbidden();<br />Response::present($req)->call(MyPresenter::class);</span></blockquote>
<br />
<br />
<h3>
ViewData</h3>
<br />
もう一つの肝が、ViewDataというデータ転送オブジェクト(DTO)。Tuum/Respondとは、要するに<b>ViewDataを設定しつつ持ちまわるため</b>のライブラリです。そして、最後にPresenterInterfaceのオブジェクトを呼び出します。<br />
<br />
このコードだと、$viewを直接いじってからテンプレートを描画します。<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">Respond::view($req)<br /> ->withViewData(function($view) use($value) {<br /> return $view->setData('key', $value);<br /> })->view('my/template');</span></blockquote>
<br />
あるいはRedirectでは、ViewDataをSessionのフラッシュに保存します。<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">Respond::redirect($req)<br /> ->withMessage('hello')<br /> ->to('/my/path');</span></blockquote>
<br />
次のリクエストで、フラッシュからViewDataを読み込むことで、データを簡単に利用することが出来ます。<br />
<br />
<br />
<h3>
インターフェース遷移</h3>
<br />
想定しているマイクロフレームワークとTuum/Respondについて、インターフェースという切り口で考えて見たら面白かったので、書いてみます。<br />
<br />
最初に、リクエストとレスポンスから**ミドルウェア**が始まります。`$next`が次のミドルウェアですね。<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">middleware($req, $res, closure $next);</span></blockquote>
<br />
ミドルウェアの最後にルーターが走り、実行する**コントローラー**を呼び出します。`$args`がルートパターンでの変数です。此処から先が、ユーザーコードに入ってゆく感じです。<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">controller($req, $res, array $args);</span></blockquote>
<br />
コントローラーでは、ドメインを操作したり、必要なビューを構築してレスポンスを返します。<br />
<br />
ビューの構築を手助けするのが、`Tuum/Respond`で、次のようなインターフェースになります。<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">viewer($req, $res, ViewData $view);</span></blockquote>
<br />
$viewに情報を設定する、テンプレートを描画する、レスポンスを構築する、など様々な処理を行えます。<br />
<br />
<blockquote class="tr_bq">
<span style="color: #45818e;">なんかMiddleware-View-Controller (MVC)みたい。</span></blockquote>
<br />
<h3>
開発は楽しい</h3>
<br />
開発していると、動くところまで作るのは楽しいとよく言われます。<br />
<br />
その後でも、リファクタリングしたり作りこむのも、理解が深まったり新しい見方が出てきたりして別の楽しさがあります。自分の趣味のパッケージでないと中々出来ないので、これからも続けてゆきたいです。<br />
<br />asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-75611724306658415422016-01-07T09:40:00.000+09:002016-01-07T11:07:06.789+09:002015年を振り返って(Tuum開発日誌メモ)2016年になったので、自分用のメモとして去年のTuumPHP開発を振り返ってみます。<br />
<br />
<h2>
Tuum/Webの開発</h2>
<br />
思えば、<a href="https://github.com/TuumPHP/Web">Tuum/Web</a>を作り始めたのは2014年の11月頃。一度ぐらい満足できるフレームワークを自作してみたい、と思い立ってしまい、<br />
<br />
<ul>
<li>良いとされる設計を積極的に使う(PSR-7、ミドルウェア、DIコンテナなど)、</li>
<li>そのうえで、自分の欲しい機能を実装する、</li>
</ul>
<br />
という方向で作り始めました。<br />
<br />
2015年5月頃には、ほぼ完成したのですが、どうも気にかかる点が出来てしまいました。おそらく、次の二点。<br />
<br />
1. 思った以上に複雑になった。<br />
2. 欲しいのはフレームワークではなかった。<br />
<br />
なので、基本ボツに。<br />
<br />
<blockquote class="tr_bq">
<span style="color: #45818e;">えぇ〜!<br />せっかく作ったのに。</span></blockquote>
<br />
<h3>
複雑すぎる</h3>
<div>
<br /></div>
一つ一つの設計は自分なりに納得して作ってるので、妙な動きはしてはいないのですが。思った以上に動きが複雑になってしまいました。原因を考えたのですが、次の2点になると思います。<br />
<br />
<ul>
<li>良いと思える設計から少しずれた、</li>
<li>自分が欲しい機能について、理解してなかった、</li>
</ul>
<br />
一番最初にミドルウェアの引数をどうするか悩んだのですが、できるだけ簡単な形を選んでしまいました。使う分には簡単そうに見えるのですが、フレームワーク側が複雑になってしまいました。<br />
<br />
自分が採用した形が、<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">$response = $middleware($request);</span></blockquote>
<br />
の形。<br />
これだと、帰ってくる$responseに対して処理を行うことが出来ません。そのため、戻りループ用の別インターフェースを作って、としているうちにコードが「ちょっと」複雑に。ちなみに、Symfonyも似たようなことをしてるので、それほど悪い実装ではないはず。<br />
<br />
一方、ほぼ標準になりつつある形が<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">$response = $middleware($request, $response, $next);</span></blockquote>
<br />
$nextとか面倒だなと思ってました。が、フレームワーク作ってみて、このAPIの良さがわかってきました。<br />
<br />
もう一点は、次のTuum/Respondの開発をして分かりました。自分の欲しかった機能を十分に理解できてなかったからです。単体のパッケージを作ることで、機能についてじっくりと考えられたわけです。<br />
<br />
<br />
<h3>
欲しいのはフレームワークではない</h3>
<br />
で、この理由。<br />
<br />
勉強のために作ったというのもあるので、そこそこ良いフレームワークができたら、もういいかなという気になった。と言うのはあります。<br />
<br />
さらに、PSR-7ベースで、素晴らしいマイクロフレームワークがいくつも出てきてます。<a href="http://www.slimframework.com/">Slim3</a>とか<a href="http://framework.zend.com/expressive">Expressive</a>。それに<a href="http://relayphp.com/">Relay</a>もミドルウェアディスパッチャーとしてよく出来てます。<br />
<br />
結局、自分が欲しいのは、先に書いた「欲しい機能」の部分であり、フレームワークではありません。すでにあるマイクロフレームワークを利用して、自分の欲しい機能が追加できれば、十分なわけです。<br />
<br />
<h3>
コーディングの勉強には最適</h3>
<br />
とはいえ、フレームワークを自作するのは、コーディングの練習には最適ですね。やってよかったなと思ってます。<br />
<br />
ということで、<a href="http://wsjp.blogspot.jp/2016/01/2015tuumrespond.html">次の開発話に続きます</a>。<br />
<br />asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-18346441966004210332015-07-06T11:29:00.000+09:002016-01-07T11:07:06.777+09:00Responder Module:フレームワークを分割して考える作ってきた<a href="https://github.com/TuumPHP/Respond">Tuum/Respond</a>が何なのか、良い説明を思いついたので書いてみます。<br />
<br />
<h2>
フレームワークの機能</h2>
<br />
最初に、フレームワークの機能を次のように分割してみます。<br />
<br />
<ol>
<li>ブートストラップとアプリ構築。</li>
<li>ルーティングとディスパッチ。</li>
<li>モデル/ドメイン実行。</li>
<li>ビューなどのリスポンス構成。</li>
</ol>
<br />
<div>
この中で、最も重要と思うのが(3)のドメイン部分。これこそがプロジェクトの本質で、一番時間を使って開発したい部分。</div>
<div>
<br /></div>
<div>
フルスタック・フレームワークとは、(3)以外のほぼすべての機能を使いやすい形にまとめあげておくことで、ドメインの開発に集中するためのものだと考えてます。</div>
<div>
<br /></div>
<div>
一方、俗にいう「マイクロフレームワーク」というのがあります。これは、(1)と(2)の部分を担っていると考えるとスッキリします。返信するのが簡単なJSONであれば、複雑なビューなどを省くことで、コードが簡潔になります。</div>
<div>
<br /></div>
<h3>
Responder Module</h3>
<div>
<br /></div>
<div>
こんなふうに分割してみると、この(4)だけをターゲットにしたミニフレームワークみたいなものがあってもいいのでは?</div>
<div>
<br /></div>
<div>
と考えて、この(4)の機能の部分を作ってみたのが「<a href="https://github.com/TuumPHP/Respond">Tuum/Respond</a>」というモジュールです。</div>
<div>
<br /></div>
<div>
ついでに、この部分に「Responder Module」と名前をつけてみました。もう名前があるのかもしれないけれど、見つからなかったので、適当に呼んだだけです。</div>
<div>
<br /></div>
<h2>
Tuum/Respond</h2>
<div>
<br /></div>
<div>
Tuum/Respondの使い方としては、例えばSlim frameworkのようなマイクロフレームワークと一緒に使うとかを想定してます。</div>
<div>
<br /></div>
<div>
<h3>
レスポンスの種類</h3>
<div>
<br /></div>
<div>
想定しているレスポンスの種類です。</div>
<div>
<br /></div>
<div>
<ul>
<li><b>View</b>:HTMLなどのコンテンツのあるレスポンス。</li>
<li><b>Redirect</b>:別URIへのリダイレクト。</li>
<li><b>Error</b>:エラー。コンテンツがある場合もある。</li>
</ul>
</div>
</div>
<div>
<br /></div>
<div>
それぞれHTTPステータスの200番台、300番台、そして400と500番台に対応します。</div>
<div>
<br /></div>
<div>
どのレスポンスを返す場合でも同じAPIが使えます。更には、リダイレクトした次のビューにデータを渡す場合でも、同じAPIになります。つまり、こんなコード。</div>
<div>
<br /></div>
<div>
<pre style="background-color: #f7f7f7; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600001335144px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; widows: 1; word-break: normal; word-wrap: normal;"><span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$app</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">new</span> <span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">App</span>(); <span class="pl-c" style="box-sizing: border-box; color: #969896;">// some micro-framework app. </span></span>
<span class="pl-s1" style="box-sizing: border-box;"></span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-c" style="box-sizing: border-box; color: #969896;">// redirects to /jumped.</span></span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$app</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>get(<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>/jumper<span class="pl-pds" style="box-sizing: border-box;">'</span></span>, <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">function</span>(<span class="pl-smi" style="box-sizing: border-box;">$request</span>, <span class="pl-smi" style="box-sizing: border-box;">$response</span>) {</span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">return</span> <span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">Respond</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">::</span>redirect(<span class="pl-smi" style="box-sizing: border-box;">$request</span>, <span class="pl-smi" style="box-sizing: border-box;">$response</span>)</span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>withMessage(<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>bad input!<span class="pl-pds" style="box-sizing: border-box;">'</span></span>) <span class="pl-c" style="box-sizing: border-box; color: #969896;">// <- set up info.</span></span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>withInputData([<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>some<span class="pl-pds" style="box-sizing: border-box;">'</span></span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=></span> <span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>value<span class="pl-pds" style="box-sizing: border-box;">'</span></span>])</span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>withInputErrors([<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>some<span class="pl-pds" style="box-sizing: border-box;">'</span></span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=></span> <span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>bad value<span class="pl-pds" style="box-sizing: border-box;">'</span></span>])</span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>toPath(<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>/jumped<span class="pl-pds" style="box-sizing: border-box;">'</span></span>);</span>
<span class="pl-s1" style="box-sizing: border-box;"> });</span>
<span class="pl-s1" style="box-sizing: border-box;"></span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-c" style="box-sizing: border-box; color: #969896;">// ...and this is jumped.</span></span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$app</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>get(<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>/jumped<span class="pl-pds" style="box-sizing: border-box;">'</span></span>, <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">function</span>(<span class="pl-smi" style="box-sizing: border-box;">$request</span>, <span class="pl-smi" style="box-sizing: border-box;">$response</span>) {</span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">return</span> <span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">Respond</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">::</span>view(<span class="pl-smi" style="box-sizing: border-box;">$request</span>, <span class="pl-smi" style="box-sizing: border-box;">$response</span>)</span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>asView(<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>template<span class="pl-pds" style="box-sizing: border-box;">'</span></span>); <span class="pl-c" style="box-sizing: border-box; color: #969896;">// with the 'welcome!' message.</span></span>
<span class="pl-s1" style="box-sizing: border-box;">});</span></pre>
</div>
<div>
<br /></div>
<div>
どこかで見たコードですね。</div>
<div>
<br /></div>
<h3>
必要なサービスとインターフェース</h3>
<div>
<br /></div>
<div>
Tuum/Respondの全ての機能を使うには、外部サービスが必要です。全てのサービスにはインターフェースが定義されています。</div>
<div>
<br /></div>
<div>
<div>
<ul>
<li><b>ViewStreamInterface:</b><br />ビュー(テンプレート展開)用API。PSR7のStreamInterfaceを継承していて、内部でテンプレートを展開。</li>
<li><b>SessionStorageInterface</b>:<br />セッションおよびフラッシュ用API。ほぼAura.Sessionのsegmentと一致してます。</li>
<li><b>ErrorViewInterface</b>:<br />エラー表示用API。</li>
</ul>
</div>
</div>
<div>
<br /></div>
<div>
これらのサービスを実装して適宜設定することになります。</div>
<div>
<br /></div>
<div>
もう少し<a href="http://wsjp.blogspot.jp/2015/06/psr7.html">細かい説明は前にブログに書いてある</a>ので、そちらも参考にしてみてください。</div>
asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-33901973445053161632015-07-01T15:42:00.000+09:002016-01-07T11:07:06.781+09:00汎用ページネーション(PSR7も使えます)<b><a href="https://github.com/TuumPHP/Pagination">汎用ページネーションのパッケージ</a></b>を作ってみた。<br />
一応、PSR7のServerRequestInterfaceも使えます。<br />
<br />
セッションを使って、ページ番号やフォーム入力を覚えるのが特徴。簡単に最後と同じページを作成できます。<br />
<br />
<h4>
何故作ったのか?</h4>
<br />
仕事でDoctrine2を採用してみたのだが、いい感じのページネーションがなかったので作ってみた。ただし仕事には間に合わなかったので、実サイトでの実績はないです。<br />
<br />
こういうページネーションに、どのぐらい需要があるのかわからないけど、この際なのでパッケージとして作ってみた。<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">ライセンス:MIT</span><br />
<span style="font-family: Courier New, Courier, monospace;">PSR準拠 :Psr-1、Psr-2、Psr-4</span><br />
<br />
<h2>
使い方</h2>
<br />
<h3>
インストール</h3>
<br />
composerで。<br />
<br />
<pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;">$ composer require <span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">"</span>wscore/pagination<span class="pl-pds" style="box-sizing: border-box;">"</span></span></pre>
<br />
<br />
<h3>
Pagerオブジェクト</h3>
<br />
Pagerオブジェクトを最初に作ります。<br />
<br />
<pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"><span class="pl-s1" style="box-sizing: border-box;"><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">use</span> <span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">WScore\Pagination\Inputs</span>;</span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">use</span> <span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">WScore\Pagination\Pager</span>;</span>
<span class="pl-s1" style="box-sizing: border-box;"></span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-c" style="box-sizing: border-box; color: #969896;">// construction</span></span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$pager</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">new</span> <span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">Pager</span>([<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>_limit<span class="pl-pds" style="box-sizing: border-box;">'</span></span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=></span> <span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">15</span>]);</span>
<span class="pl-s1" style="box-sizing: border-box;"></span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-c" style="box-sizing: border-box; color: #969896;">// set up pager using Psr-7 ServerRequestInterface.</span></span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$pager</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=</span> <span class="pl-smi" style="box-sizing: border-box;">$pager</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>withRequest(<span class="pl-smi" style="box-sizing: border-box;">$request</span>);</span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-c" style="box-sizing: border-box; color: #969896;">// or from global data. </span></span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$pager</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=</span> <span class="pl-smi" style="box-sizing: border-box;">$pager</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>withQuery(<span class="pl-smi" style="box-sizing: border-box;">$_GET</span>, <span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>/find<span class="pl-pds" style="box-sizing: border-box;">'</span></span>);</span></pre>
<br />
次に、データベースへのクエリなどを実行します。callメソッドにクロージャーを渡してください。引数はInputsというクラスのオブジェクトです。<br />
<br />
<pre style="background-color: #f7f7f7; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600001335144px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; widows: 1; word-break: normal; word-wrap: normal;"><span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$inputs</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=</span> <span class="pl-smi" style="box-sizing: border-box;">$pager</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>call(</span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">function</span>(<span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">Inputs</span> <span class="pl-smi" style="box-sizing: border-box;">$inputs</span>) <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">use</span>(<span class="pl-smi" style="box-sizing: border-box;">$pdo</span>) {</span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-c" style="box-sizing: border-box; color: #969896;">// query the PDO!</span></span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-smi" style="box-sizing: border-box;">$found</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=</span> <span class="pl-smi" style="box-sizing: border-box;">$pdo</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>prepare(<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-s1" style="box-sizing: border-box; color: #333333;"><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">SELECT</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">*</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">FROM</span> tbl <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">WHERE</span> type<span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=</span>? <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">and</span> num<span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">></span>? OFFSET ? <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">LIMIT</span> ?</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>)</span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>execute([</span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-smi" style="box-sizing: border-box;">$inputs</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>get(<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>type<span class="pl-pds" style="box-sizing: border-box;">'</span></span>),</span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-smi" style="box-sizing: border-box;">$inputs</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>get(<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>num<span class="pl-pds" style="box-sizing: border-box;">'</span></span>),</span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-smi" style="box-sizing: border-box;">$inputs</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>getOffset(),</span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-smi" style="box-sizing: border-box;">$inputs</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>getLimit(),</span>
<span class="pl-s1" style="box-sizing: border-box;"> ])</span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>fetchAll();</span>
<span class="pl-s1" style="box-sizing: border-box;"> <span class="pl-smi" style="box-sizing: border-box;">$inputs</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>setList(<span class="pl-smi" style="box-sizing: border-box;">$found</span>);</span>
<span class="pl-s1" style="box-sizing: border-box;"> });</span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$found</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=</span> <span class="pl-smi" style="box-sizing: border-box;">$inputs</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>getList();</span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$type</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=</span> <span class="pl-smi" style="box-sizing: border-box;">$inputs</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>get(<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>type<span class="pl-pds" style="box-sizing: border-box;">'</span></span>);</span></pre>
<br />
後は、クロージャー内で必要な処理を書き込みます。<br />
Inputsオブジェクトから、オフセットとリミットや、フォームの入力を読み取れます。<br />
<br />
<h3>
HTML出力</h3>
<br />
最後に、HTMLへの出力は、Paginateというオブジェクトを使います。<br />
<br />
<div class="highlight highlight-php" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 17.0666675567627px; margin-bottom: 16px; widows: 1;">
<pre style="background-color: #f7f7f7; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600001335144px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"><span class="pl-s1" style="box-sizing: border-box;"><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">use</span> <span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">WScore\Pagination\Html\Paginate</span>;</span>
<span class="pl-s1" style="box-sizing: border-box;"></span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$inputs</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>paginate(<span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">new</span> <span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">Paginate</span>());</span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">echo</span> <span class="pl-smi" style="box-sizing: border-box;">$inputs</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>__toString();</span></pre>
<div>
<span class="pl-s1" style="box-sizing: border-box;"><br /></span></div>
<div>
<br /></div>
<div>
すると、こんなページネーションが表示されます。</div>
<div>
<br /></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsDG7mn5mZjccmDhlUK4GJ1AwNyryZlUxsg70NRfoq3Mkts6k_bevP-t1QGAC83XLnsVQcyz5zrLGByS66Lpg-efLbyOBc_y5z-zKAHEyj7eXta3m_uKpqj9RUMxVWPRzKZ_i5Jlp5i9s/s1600/Tuum+Pagination1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsDG7mn5mZjccmDhlUK4GJ1AwNyryZlUxsg70NRfoq3Mkts6k_bevP-t1QGAC83XLnsVQcyz5zrLGByS66Lpg-efLbyOBc_y5z-zKAHEyj7eXta3m_uKpqj9RUMxVWPRzKZ_i5Jlp5i9s/s1600/Tuum+Pagination1.png" /></a></div>
<br />
<h2>
リクエストの仕方</h2>
ここが、このパッケージの肝になります。<br />
<b>「_page」</b>を使いこなします。<br />
<br />
<h3>
1.検索条件フォーム</h3>
<br />
ページネーションを行う場合は、検索条件をフォームで選ぶ場合が多いと思います。その場合は、普通にフォームを作ってください。<br />
<br />
<pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"><<span class="pl-ent" style="box-sizing: border-box; color: #63a35c;">form</span>>
<<span class="pl-ent" style="box-sizing: border-box; color: #63a35c;">input</span> <span class="pl-e" style="box-sizing: border-box; color: #795da3;">type</span>=<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">"</span>text<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: #795da3;">name</span>=<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">"</span>type<span class="pl-pds" style="box-sizing: border-box;">"</span></span> />
<<span class="pl-ent" style="box-sizing: border-box; color: #63a35c;">input</span> <span class="pl-e" style="box-sizing: border-box; color: #795da3;">type</span>=<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">"</span>integer<span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: #795da3;">name</span>=<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">"</span>num<span class="pl-pds" style="box-sizing: border-box;">"</span></span> />
<<span class="pl-ent" style="box-sizing: border-box; color: #63a35c;">input</span> <span class="pl-e" style="box-sizing: border-box; color: #795da3;">type</span>=<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">"</span>submit<span class="pl-pds" style="box-sizing: border-box;">"</span></span> />
</<span class="pl-ent" style="box-sizing: border-box; color: #63a35c;">form</span>></pre>
<br />
注意:_pageは使わないで下さい。<br />
フォームの内容は自動でセッションに登録されます。セッションは事前に走らせておいて下さい。<br />
<h3>
2.ページの指定</h3>
<br />
指定するページを表示するには_pageにページ番号を指定します。<br />
<br />
<pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; line-height: inherit; margin: 0px; max-width: initial; overflow: initial; padding: 0px; word-break: normal; word-wrap: normal;">GET /find?_page=2</code></pre>
<br />
検索に使う条件はセッションに保持されているので、同じ条件でオフセットを替えてクエリを実行できます。<br />
<br />
<h3>
3.最後の検索画面</h3>
<br />
検索画面を表示する際、_pageにページ番号をなしでGetしてみてください。<br />
<br />
<pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; line-height: inherit; margin: 0px; max-width: initial; overflow: initial; padding: 0px; word-break: normal; word-wrap: normal;">GET /find?_page</code></pre>
<br />
すると、セッションから最後のページ番号と検索条件を読みだします。<br />
<br />
<h2>
To Do</h2>
<br />
動くはずですが、実際に使ったことがないのでAPIなど変わるかもしれません。なのでアルファリリースです。<br />
<br />asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-31686816483036361062015-06-12T06:34:00.000+09:002015-06-27T11:45:36.685+09:00PSR7用のヘルパーとレスポンダーコツコツとフレームワークを作っていて。<br />
ふと、自分が欲しかったのは、もっと簡単なことじゃないか?と思い直して作ったのが<span style="color: #999999;"><b>「</b><b>Tuum/Http」</b>というパッケージ。</span><br />
<br />
<b>【修正:2015/06/26】</b><br />
<b>「<a href="https://github.com/TuumPHP/Respond">Tuum/Responder</a>」に名前を変更しました。</b><br />
<br />
そもそものスタートとして、SlimやStackPHPの簡潔な構造に憧れたところから始まっている。が、実際に使うとなると、API作るには便利だけれど、普通のウェブサイトを構築するには作業が面倒そうだなぁと。<br />
<br />
面倒だと思った部分は、レスポンスを返す部分。たとえば前のページに戻ったり、ついでにメッセージやエラー情報を付加したりという部分。同じような処理が多い割には、細かな設定が必要な気がする。<br />
<br />
そこで、この部分だけをパッケージにしてみた。<br />
<br />
<br />
<h2>
何をするパッケージなのか</h2>
<br />
<div>
<br />
大きくヘルパーとレスポンダーからできている。<br />
大事なのはレスポンダーの方。</div>
<div>
<br /></div>
<h3>
ヘルパー</h3>
Psr7に足りなさそうな機能をスタティックなメソッドとして提供している。見れば一発、簡単なものばかり。例えば、<br />
<br />
<pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"><span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$bool</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=</span> <span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">ResponseHelper</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">::</span>isRedirect(<span class="pl-smi" style="box-sizing: border-box;">$response</span>);</span></pre>
<br />
<div>
はリダイレクトレスポンスかどうかをチェックできる。RequestHelperとResponseHelperの2つがある。</div>
<div>
<br /></div>
<h3>
レスポンダー</h3>
<div>
レスポンスを構築するためのヘルパー。</div>
<div>
例えば、別パスにリダイレクトしたり、その際にメッセージを付加できる(単にセッション・フラッシュに登録してるだけだが)。</div>
<div>
<br /></div>
<div>
<pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"><span class="pl-s1" style="box-sizing: border-box;"><span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">Redirect</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">::</span>forge(<span class="pl-smi" style="box-sizing: border-box;">$request</span>, <span class="pl-smi" style="box-sizing: border-box;">$response</span>)<span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>withMessage(<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>welcome!<span class="pl-pds" style="box-sizing: border-box;">'</span></span>)<span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>toPath(<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>jump/to<span class="pl-pds" style="box-sizing: border-box;">'</span></span>);</span>
<span class="pl-s1" style="box-sizing: border-box;"></span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-c" style="box-sizing: border-box; color: #969896;">// ...now in the subsequent request to a server...</span></span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">Respond</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">::</span>forge(<span class="pl-smi" style="box-sizing: border-box;">$request</span>, <span class="pl-smi" style="box-sizing: border-box;">$response</span>)<span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>asView(<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>template<span class="pl-pds" style="box-sizing: border-box;">'</span></span>); <span class="pl-c" style="box-sizing: border-box; color: #969896;">// with the 'welcome!' message.</span></span></pre>
</div>
<div>
<br /></div>
<div>
次のリクエストの際に、前のメッセージが自動でビューに入ってくる。メソッド名がどこかで見たことのあるのは愛嬌。使いやすいと思ったので。<br />
<br />
レスポンダーとしては、<b>Respond</b>、<b>Redirect</b>、そして<b>Error</b>がある。それぞれ、ビューを返す、リダイレクトを返す、エラーページを返す。</div>
<div>
<br /></div>
<h2>
使うのに必要なこと:サービス</h2>
<div>
<br /></div>
<div>
レスポンダーの機能を実現するために、ビューやセッションなどのサービスを使っている。これを作っておいて、レスポンダーに渡す必要がある。</div>
<div>
<br /></div>
<h3>
セッション用インターフェース</h3>
<div>
セッションのフラッシュを使ってリクエスト間のデータを受け渡している。そのためのセッションとしてSessionStorageInterfaceという形で定義した。</div>
<div>
<br /></div>
<div>
と行っても、実際はAura.SessionのSegmentと同一のAPI。これを使うのが前提みたいになっている。</div>
<div>
<br /></div>
<div>
<pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"><span class="pl-s1" style="box-sizing: border-box;"><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">use</span> <span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">Aura\Session\SessionFactory</span>;</span>
<span class="pl-s1" style="box-sizing: border-box;"></span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$factory</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">new</span> <span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">SessionFactory</span>();</span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$session</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=</span> <span class="pl-smi" style="box-sizing: border-box;">$factory</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>newInstance(<span class="pl-smi" style="box-sizing: border-box;">$_COOKIES</span>);</span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$segment</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=</span> <span class="pl-smi" style="box-sizing: border-box;">$session</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>getSegment(<span class="pl-s" style="box-sizing: border-box; color: #183691;"><span class="pl-pds" style="box-sizing: border-box;">'</span>some-name<span class="pl-pds" style="box-sizing: border-box;">'</span></span>);</span></pre>
</div>
<div>
<br /></div>
<div>
ここで作った$segmentがSessionStorageInterfaceと同じオブジェクトになる。</div>
<div>
<br /></div>
<div>
<div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; margin-bottom: 16px;">
これを$requestに設定する。</div>
<div class="highlight highlight-php" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 20.4799995422363px; margin-bottom: 16px;">
<pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"><span class="pl-s1" style="box-sizing: border-box;"><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">use</span> <span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">Tuum\Http\RequestHelper</span>;</span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$request</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=</span> <span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">RequestHelper</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">::</span>withSessionMgr(<span class="pl-smi" style="box-sizing: border-box;">$request</span>, <span class="pl-smi" style="box-sizing: border-box;">$segment</span>);</span></pre>
<div>
<span class="pl-s1" style="box-sizing: border-box;"><br />
</span></div>
</div>
</div>
<div>
あるいは、後で書くようにコンテナに設定しておく方法もある。</div>
<div>
<br /></div>
<h3>
ビュー用インターフェース</h3>
<div>
HTMLを返すにはテンプレートを使ったビューを使いたい。そのために、ビューを展開するViewStreamInterfaceを定義してみた。</div>
<div>
<br /></div>
<div>
テンプレートを展開できるStreamとして扱う。</div>
<div>
<br /></div>
<h3>
ViewDataクラス</h3>
<div>
これは実際のクラス。</div>
<div>
ビューやリクエスト間でデータをやりとりするためのデータ転送用オブジェクト。</div>
<div>
<br /></div>
<div>
ビュー用のクラスはViewDataを理解して、実際のレンダラーに渡す必要がある。</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
コンテナー用インターフェース</h3>
<div>
サービスを管理するコンテナ。Container-Interopで定義したインターフェースを使った。これに必要なサービスを登録しておいて、$requestに設定する。<br />
<br />
次はセッションを設定する方法。<br />
<br />
<pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"><span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$app</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">=</span> <span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">new</span> <span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">Container</span>(); <span class="pl-c" style="box-sizing: border-box; color: #969896;">// must implement ContainerInterface</span></span>
<span class="pl-s1" style="box-sizing: border-box;"><span class="pl-smi" style="box-sizing: border-box;">$app</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span><span class="pl-smi" style="box-sizing: border-box;">set</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">-></span>(<span class="pl-c1" style="box-sizing: border-box; color: #0086b3; font-size: 13.6000003814697px; line-height: 1.45;">SessionStorageInterface</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d; font-size: 13.6000003814697px; line-height: 1.45;">::</span><span class="pl-c1" style="box-sizing: border-box; color: #0086b3; font-size: 13.6000003814697px; line-height: 1.45;">class</span><span style="font-size: 13.6000003814697px; line-height: 1.45;">, </span><span class="pl-smi" style="box-sizing: border-box; font-size: 13.6000003814697px; line-height: 1.45;">$segment</span><span style="font-size: 13.6000003814697px; line-height: 1.45;">);</span></span><span class="pl-s1" style="box-sizing: border-box;"><span class="pl-c1" style="box-sizing: border-box; color: #0086b3;">RequestHelper</span><span class="pl-k" style="box-sizing: border-box; color: #a71d5d;">::</span>withApp(<span class="pl-smi" style="box-sizing: border-box;">$request</span>, <span class="pl-smi" style="box-sizing: border-box;">$app</span>);</span></pre>
<br />
<br />
<br />
<br /></div>
asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-54048870980465343732015-05-24T16:21:00.000+09:002015-06-12T06:34:20.307+09:00PHPの__invokeメソッドの使いドコロは?PHPにはクロージャー(無名関数)と、クラスを無名関数のように使えるようになるマジックメソッド、__invoke、というのがある。これに関する雑感。<br />
<br />
クロージャーと言うのは便利なもので、プログラムをデータとして扱える。<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">$hello = function($world) {<br /> return 'hello ' . $</span><span style="font-family: 'Courier New', Courier, monospace;">world</span><span style="font-family: Courier New, Courier, monospace;">;<br />};</span></blockquote>
<span style="font-size: x-small;">便利なケースを思いつかなかったので、適当に書いたコード。</span><br />
<br />
<br />
<b>一方で、__invokeメソッドの使いドコロは何だろう。</b><br />
<br />
自分が思いつくのは、<br />
1.流行りのファンクショナルな言語のように書ける。<br />
2.メソッド名を考えなくても使える。<br />
3.クロージャーの代わりにオブジェクトを使いたい場合に必要。<br />
<br />
最初の1.と2.は冗談なので、実際は3.の場合かなと思える。つまり何かの関数の引数としてクロージャーを想定している場合でも、オブジェクトが使える。<br />
<br />
でも3.の理由は、クラス自体でのメリットというより、必要だからという感じがする。<br />
<br />
あとPHPの問題として、意外なところでコードのパースが悪いところがある。せっかくコンパクトに書けるはずのクロージャーなのに、かえってコードが複雑になってしまう。<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">class Hello {<br /> private $hello;<br /> function __construct($hello) {<br /> $this->hello = $hello;<br /> }<br /> function hello($world) {<br /> return $this->hello($world); // 動かない!<br /> }<br />}</span></blockquote>
<br />
なんで、こんなことを書いてるかって?<br />
<br />
いや、1.と2.の理由で__invoke使って見たら、意外と面倒で。一方で感じたメリットは3.しかなかったので。それで__invokeメソッドを使うメリットは他に何があるか?そんなことを思ったのでブログに書いてみた。<br />
<br />asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-42883820414382536392015-05-24T08:52:00.003+09:002015-05-24T08:52:55.301+09:00自作フレームワークでのミドルウェア設計自作中のウェブアプリケーションフレームワークではミドルウェアベースで動きます。基本は「<a href="http://qiita.com/asaokamei/items/7ab97852cff5603f5145">StackPHPとミドルウェア</a>」に書いたとおりですが、実際のインターフェースに落とすまでの過程についてまとめてみます。<br />
<br />
と、Blogspotでコードを書くのが面倒なのを思い出したので、<a href="https://gist.github.com/asaokamei/4a9a3c98e63f8ff31b7e">gist</a>に書いた。<br />
<br />
フレームワークの文章としては、もっと簡潔に必要な箇所だけにまとめる必要があるだろうな。asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-26057893893051893072015-04-03T17:04:00.000+09:002015-05-18T15:00:34.785+09:00ミドルウェアベースでPSR7を使った自作フレームワーク相変わらずフレームワークを自作している。勉強になるし、万が一、いいものができたら実際に使ってみたいと思いながら作っている。今までは、勉強がメインだったが、今回は本当に使えそうな感じになってきた。<br />
<br />
名前は「<a href="https://github.com/TuumPHP">TuumPHP</a>」。<br />
<br />
<h2>
作り始めたきっかけ</h2>
<h3>
StackPHPとLaravel</h3>
<br />
2014年の夏頃、Laravel4.2で開発をしていて、これは楽に開発できるフレームワークだなぁと関心した。ただ自分の仕事だとアップデートについて行くのは難しいと感じていた。一旦作ったら、作り変えない程度の機能追加がたまにある程度で、数年は運用する必要がある。まぁなんとかなると思うけど。<br />
<br />
そんな時、ミドルウェアとStackPHPについて調べてみて、これは素晴らしいと。単純な構造を組み合わせることで複雑なアプリを構築することができて、PHPの方向はこれだと思った。こんなエントリをQiitaにアップしている<br />
<br />
「<a href="http://qiita.com/asaokamei/items/7ab97852cff5603f5145">StackPHPとミドルウェアについて調べてみた</a>」<br />
<br />
つまり、<br />
<br />
<ul>
<li>StackPHPのような簡潔な構造で、</li>
<li>Laravelのように開発しやすいくて、</li>
<li>データの流れが自然(ファサードとか使わない)、</li>
<li>できればバージョンアップもパッケージ別に対応可、</li>
</ul>
<br />
そんなフレームワークがほしいと思った。<br />
<br />
ちょいと探したけれど、いいのが見つからず。じゃ、自分で作ってみるか、というのが始まり。<br />
<br />
<h3>
Psr-7の導入</h3>
<br />
作ってからしばらくして、標準のHTTPリクエストやレスポンスの規格がもうそろそろ完成するという話が流れてきた。Psr-7という規格。しかも不変オブジェクトが使われている、ときいて早速導入して見た。<br />
<br />
その時の経験からQiitaに書いたのが、<br />
<br />
「<a href="http://qiita.com/asaokamei/items/b86e384867bcf0379cea">Psr7を使ってみた(というか不変オブジェクトを初めて使った感想)</a>」<br />
<br />
<br />
<h2>
TuumPHPの特徴</h2>
余り思いつかないので、徒然と書いてみる。<br />
<br />
マイクロフレームワーク+ビュー。<br />
つまりSlimやSilexより少し機能が豊富なフレームワーク。モデル側(DB)などは持ってない。<br />
<br />
<h3>
マジックな機能</h3>
<br />
つまりLaravelから拝借した機能、ということですね。<br />
<br />
<ul>
<li>フォームの入力エラーで、フォームにリダイレクトで戻るときに、入力値(withInputs)やバリデーションエラー(withErrors)などを一緒に返せる。</li>
<li>フォームに値を表示するときに、リダイレクトの戻り値(withInputs)を簡単に利用できる。</li>
<li>APIやメソッド名を参考に。</li>
</ul>
<br />
意外と少なかった。<br />
<br />
<h3>
ミドルウェア</h3>
<br />
なんでもミドルウェア。<br />
<br />
ルーティングもミドルウェアなので、いくつでも追加できる。ルーティングの前のプリ・ルーティングも、ルーティング後のコントローラ内のポスト・ルーティングもできる。<br />
<br />
ルーティングの後のディスパッチャーもミドルウェア。これも交換可能。<br />
<br />
もちろんコントローラーもミドルウェアの一つ、ので、単純な継承でコントローラークラスを作れる。というか継承する必要は無いはず。<br />
<br />
コントローラ内で簡易ルーティングができる。貧者のアノテーション・ルーティングですね。<br />
<br />
<h3>
状態</h3>
<br />
まだアルファ。<br />
APIも含めて色々と変わる可能性は高い。<br />
<br />
独立したコンポーネントを作っていて、こちらはドキュメントとテストはそこそこあるが、フレームワークとしてはドキュメントもテストもほぼ未着手。<br />
<br />
その代わり、<a href="https://github.com/TuumPHP/byof/blob/master/README.ja.md">こんな文章</a>を書いている。フレームワークの使い方ではなくて、どうしてこうなった?の理由を書いたほうが勉強になるかなと思ったから。<br />
<br />
<br />
<h3>
今後</h3>
<br />
すでにZend FrameworkもSlim Framework も次のバージョンでPsr-7でミドルウェアに対応すると表明している。。Laravel 5もすでにミドルウェアベースになっているし、次にはPsr-7を使ってくるのでは無いかと思う。<br />
<br />
注目したいのは、今後のPHPで<br />
<b><i><span style="font-size: large;"><br /></span></i></b>
<br />
<div style="text-align: center;">
<b><i><span style="font-size: large;"><b><i><span style="font-size: large;">よく使われるミドルウェアAPI</span></i></b></span></i></b></div>
<br />
<br />
はどれか、という点。APIが同じなら互換性が高いため、コードやオブジェクトを共通して使える。例えばOAuthとかのクラスを使いまわせるかどうか、というのが大事。<br />
<br />
もしフレームワークを自作するなら、APIの目安がついてからのほうがいいと思う。<br />
<br />asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-28086193784947182062014-12-18T16:35:00.000+09:002015-05-18T15:01:12.855+09:00Software Designの2015年1月号「ソフトウェア開発の未来」久々に本屋でIT関連の雑誌を買った。<br />
ランチの後に、近くの本屋に入って手にとって見たのが、<br />
<br />
<a href="http://gihyo.jp/magazine/SD/archive/2015/201501">Software Designの2015年1月号</a><br />
<br />
タイトルは「Vim使い事始め」だけど、目に止まったのは「ソフトウェア開発の未来」のほう。特にサブタイトル<b>「請負・受託開発は変わるべきか?」</b>が決定的だった。<br />
<br />
内容は、渋い。<br />
目新しいことや、びっくりするようなことは書いてない。<br />
知ってた、みたいな話も多い。<br />
<br />
でも、こういう普通の話を聞く機会というのは少ないので、タメになる。<br />
<br />そして考えがスッキリした気がする。<br />
モヤモヤと思ってたことを、整頓した感じ。<br />
<br />
これからもSIという名前の請負案件はなくならない。日本のIT業界内でのシェアは減ってゆくと思う。が、絶対的な金額としては、特に中小規模は減らないのではないかと思う。<br />
<br />
そして自分はお客さんと話をして要件を聞いたりまとめたりするのは好きだ。二次三次の下請けにならない限り、請負仕事は続けてゆくと思う。ただ直接お客さんと話せない状態になったらわからないかな。<br />
<br />
今日のポイント。<br />
<br />
設計力は大事。<br />
シンプルな技術で長期間のサポート。<br />
そしてお客様の困っていることを解決すること。<br />
<br />asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-62994517838643913522014-11-13T17:05:00.000+09:002015-05-18T15:00:34.795+09:00フレームワーク自作したい病が発生したあまりに内容が薄いメモなので、自分のブログで書くことに。下書きみたいなものかと思われる。<br />
<br />
StackPHPを参考に<a href="https://github.com/asaokamei/Pile">フレームワーク自作</a>を始めた。自作すると大変、と言うのは経験済みだが、自作したくなってしまったのは仕方がない。<br />
<br />
さて、大事な方向性は。<br />
<br />
<ol>
<li>StackPHPのように「<b>ミドルウェアのスタック</b>」でウェブアプリを構築する。ただし、StackPHPは使わずに自作することに(理由は後述)</li>
<li>できるだけミドルウェア側に処理を寄せること。</li>
<li>ミドルウェアはできるだけ疎結合であること。</li>
<li>既存のライブラリを有効に利用すること。</li>
<li>ウェブサーバーのフロントに特化。DBなどのインフラ周りは含まない。</li>
<li>ひとまずDIコンテナは利用しない。</li>
</ol>
<div>
書いてみたら真っ当な内容で、特に目新しさが感じられない。でも、調べたところではStackPHPを使ったフルフルなフレームワークが見つからなかった。</div>
<div>
<br /></div>
<h3>
StackPHPを使わなかった理由</h3>
<div>
StackPHPのミドルウェアとして次の3つを満たす必要がある。</div>
<div>
<ol>
<li>SymfonyのHttpKernelInterfaceを実装すること。</li>
<li>コンストラクターの第一引数として次のミドルウェアを受け取ること。</li>
<li>(必要であれば)handleメソッドの中で、次のミドルウェアを呼び出して結果を返すこと。</li>
</ol>
<div>
疑問に感じたのは、ミドルウェアの中に、「実際の処理」と「次の処理を呼び出す」、という<b>2つの責務を持っている</b>こと。多すぎるんじゃないか?!</div>
</div>
<div>
<br /></div>
<div>
例えば認証とかフィルターを考えてみる。</div>
<div>
使い方としては、ミドルウェアとしてスタックの中に放り込んで、全アクセスで必ず認証をさせる。あるいは認証する条件(URLなど)をつける。そしてbeforeなど特別な場所から認証フィルターを掛けてみる。</div>
<div>
などなど、いろんな使い方が想定できる。</div>
<div>
<br /></div>
<div>
つまり、次のミドルウェアを呼ばない使い方も多いようにみえる。そうなら、この<b>ミドルウェアは処理部分とスタックの部分を分離する</b>ほうがよくない?と思った。</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
で作ったのが<a href="https://github.com/asaokamei/Pile/blob/f381c8eb6dfcdfcfd13907a4213fb10cc4e762d6/src/Stack/Stackable.php">Stackableというクラス</a>。これにHttpKernelInterfaceを実装した処理オブジェクトを<a href="https://github.com/asaokamei/Pile/blob/f381c8eb6dfcdfcfd13907a4213fb10cc4e762d6/src/Stack/Stackable.php#L91">push</a>してあげると、次のスタックになる。スタックの考えが単純なので、コード自体は簡単だ。</div>
<div>
<br /></div>
<h3>
DIコンテナは?</h3>
<div>
今後、PHPでもDIコンテナは重要な、いや使って当然な技術になってゆくと思う。が、今はいろんなコンテナが乱立しているし、標準もないし、使ってみると「遅いし」。</div>
<div>
<br /></div>
<div>
なので、ひとまずDIコンテナなしで作ってみることに。ただし依存性の注入は行うことにして、単純なfactory methodを使う方向で作ってます。</div>
<div>
<br /></div>
<h3>
ミドルウェア作成してみた感想</h3>
<div>
実際にミドルウェアを作ってみると、意外と疎結合しないことがわかった。不便なままならいいけれど、やっぱり楽に開発したいと思うとマジックが必要になる。</div>
<div>
<br /></div>
<div>
例えばResponseを返すミドルウェアが複数存在する。一方、ここはフレームワークで統一したい(というか簡単にしたい)と思ったとする。結局、リスポンスオブジェクトを作るファクトリをアプリの中に持っておいて、必要に応じて取り出しては使う、みたいなコードがあちこちに散乱している。</div>
<div>
<br /></div>
<div>
データも共有することが多い。例えばリダイレクトしたら、ちょっとしたデータを一緒にセッションで送りたい。つまりリダイレクト部とセッションでデータを共有する必要がある。後CSRFトークンとかね。</div>
<div>
<br /></div>
<br />
<div>
こういう疎結合しながら共有するパターンといえばイベント(Event AggregatorやMediatorパターン)らしい。</div>
<div>
<br /></div>
<div>
しかしながらですよ、ミドルウェアは順番に実行するものですよね。勝手にpushするイベント系は、スタックとは相性が悪いのでは?。なので、「ひとまず」データやオブジェクトをアプリにpush/pullをするようにして、必要に応じて共有することにしてみた。もう少し他のFWの実装を調べてみる予定。</div>
<div>
</div>
<br />
<div>
<br /></div>
<h3>
ライブラリについて</h3>
<div>
今、使っているライブラリ。意外と少なかった。</div>
<div>
<ul>
<li>symfony/http-foundation<br />スタックの基本なので、絶対外せない。</li>
<li>symfony/routing<br />ルーティングに使う予定。もっと簡単なのを探してます。</li>
<li><a href="http://flysystem.thephpleague.com/">league/flysystem</a><br />設定ファイルを管理するためのファイルシステム。これにUnionManagerというのをかぶせることで、環境(productionやlocal)による設定を処理させる予定。</li>
<li><a href="http://platesphp.com/engine/">league/plates</a>, <a href="https://github.com/auraphp/Aura.View">aura/view</a><br />生PHPベースのテンプレート。どちらを使うかは検討中。</li>
<li><a href="https://github.com/asaokamei/WScore.Form">wscore/form</a><br />自作のHTMLフォーム生成コンポーネント。遅延評価でFluentにフォームが書けます。</li>
</ul>
</div>
<div>
<br /></div>
<div>
<br /></div>
asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-53250167691857227392014-04-21T14:34:00.004+09:002015-05-18T15:00:34.790+09:00LaravelのEloquent ORMについてQiitaに書いてみた最近LaravelフレームワークのEloquent ORMを触ってます。まだ始めたばかりですが、2つほどQiitaに気がついたことをまとめてみました。<br />
<br />
<a href="http://qiita.com/asaokamei/items/bdad9d0f931f0840a3a9">Eloquentのモデル生成法比較:newとcreate</a><br />
<br />
<a href="http://qiita.com/asaokamei/items/ce87090c155d7b4d7f6d">Eloquentでリレーションを作成する方法</a><br />
<br />
<br />
やはりMarkdown記法でかけるのがいいな。<br />
特にソースコードの記述が楽だ。githubのお陰です。<br />
<br />
Bloggerでも使えるようになるといいのだけど。asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-69413817255551588302014-01-17T09:24:00.002+09:002014-01-17T09:24:23.058+09:00PHPでファイルポインターからファイル名を取得する方法ちょっと調べたら<a href="http://stackoverflow.com/questions/5144583/getting-filename-or-deleting-file-using-file-handle">StackOverflowで見つけた方法</a>。<br />
日本語のページが少なかったので書いてみる。<br />
<br />
関数内で、ファイルポインターだけ渡されたのにファイル名が知りたい場合が出てきました。<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">$fp = fopen( $filename, 'r' );<br />function get( $fp )<br />{<br /> $filename = ... // ここでファイル名が知りたい。<br />}</span></blockquote>
<br />
引数にファイル名を追加すればいいのですが、面倒だったのでちょっと調べたら、すぐに答えが見つかりました。<a href="http://php.net/manual/ja/function.stream-get-meta-data.php">stream_get_meta_dataという関数</a>。さすがPHPです。関数ほぼ一発で取得できました。<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">$info = stream_get_meta_data($fp);<br />$filename = $info["uri"];</span></blockquote>
<div>
<br /></div>
<div>
だそうです。</div>
<div>
<br /></div>
asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-53453090748510378272014-01-03T17:17:00.002+09:002014-01-18T08:30:37.598+09:002014年の抱負は「勉強」あまり「勉強」は好きな言葉ではないけど。<br />
そして、<a href="http://wsjp.blogspot.jp/2013/12/2013.html">もう書いたようなもの</a>だけど。<br />
<br />
簡単に言えば、<br />
<blockquote class="tr_bq">
<b>昨年は頑張ってアウトプット(コード)したら、<br />知識不足を痛感したので、<br />今年はインプット(勉強)を頑張ろう、</b></blockquote>
という話です。<br />
<div>
<br /></div>
<div>
■</div>
<div>
<br class="Apple-interchange-newline" />何を勉強するのか。</div>
<div>
<br /></div>
<div>
まずはOOPの基礎やDDDからかなぁ。</div>
<div>
マーティン・ファウラーの、あの本は購入済みなので、それを読もう。</div>
<div>
<br /></div>
<div>
後は、Doctrine2やAuraPHPなど、他のフレームワークを勉強したい。ただ全部入りより、各コンポーネントが充実&使いやすい、というコードを勉強したい。</div>
<div>
<br /></div>
<div>
<div>
■</div>
</div>
<div>
<br /></div>
ただ、嫌いなことを頑張るのは難しい。<br />
ひとまず、無理をしない程度がよいはず。<br />
<br />
今、<b>一番無理をしているのは目</b>かも。<br />
最近、目が疲れて仕事が続かないことが増えた。<br />
<br />
ツイッターで、面白そうなリンクやブログを読むのも良いけれど、なるだけモニターを見つめる時間を減らして、目の使い方を変えたい。ということで、できれば<b>本を読んで勉強できれば</b>よいなと考えてます。<br />
<div>
<br /></div>
asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-51385055350402713202013-12-29T10:58:00.000+09:002014-01-18T08:30:45.883+09:00Frameworkに依存しないcodeをどう書くか元々はSymfonyのLTSが3年間というところから。<br />
え〜、そんなに短いんだ。<br />
<br />
フレームワーク(FW)よりビジネスのほうが長生きなので、フレームワークに依存しないコードが書きたいな、と。<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;">もっともFWのサポート期間とはなんだろう?期間が過ぎても動くものは動いているし、PHPとかアップグレードしなければ(!)大丈夫なはずだし。脆弱性は最初から入ってないという仮定も必要だけど。</span></blockquote>
本来、プロジェクトで一番大事な部分はFWというより、それ以外の部分だと思う。それ以外の部分、と言うのはMVCでのモデルというところか。あるいはDDDで言うドメインというところか。<br />
<div>
<br /></div>
その部分がFWに依存しなければ、何も悩む必要はない、はず。<br />
<br />
その部分をどう書くのかな、と最近考え始めた。<br />
<br />
■<b>DDDとDCI</b><br />
<br />
モデルやドメインといえばDDD。あるいはDCI。<br />
<br />
ただDDDとかDCIなど、どうPHPコードに落とせばいいのだろうか?どう書くと、仕様が分かりやすい、テストしやすいコードになるのか。今のところさっぱり。<br />
<div>
<br /></div>
一方、今の仕事でDDDが必要になるほど複雑な仕様は無いという話もある。ということで、今後少しずつ勉強する予定。<br />
<br />
■<b>FWとのインターフェース</b><br />
<br />
モデル・ドメインを分離して書いても、フレームワークとのインターフェースは必要だ。ここがFW依存になるので、何かを挟む、ということになるのだろうか?<br />
<br />
モデルを、ひとまずエンティティと考えれば、エンティティとフレームワークとの接点は、<br />
*Persistence、<br />
*Validation、<br />
*Presentation、<br />
それと、DBやHTMLフォームはテキストベースなので、エンティティとテキストの変換機能も必要かも。これぐらいあれば、簡単なことなら出来そう。<br />
<div>
<br /></div>
ということで、以上を抽象化したFWモデルを作っておけば、フレームワークが変わってもFWモデルを変えるだけで、ドメイン側には修正は必要ない、とか考えている。<br />
<br />
■<b>ちょっと作ってみた</b><br />
<br />
この1年以上PHP5.3で新フレームワークを開発していたら、受注した仕事がPHP5.2ばかり。ということで、PHP4時代から使っているライブラリで開発する羽目になった。<br />
<br />
頭にきたので、<a href="https://github.com/asaokamei/Models">FWモデル</a>を書いてみた。<br />
モデル内で、PHP4時代(コンストラクターがクラス名とかw)のオブジェクトをnewしまくりながら、ぱっと見は格好良いクラスに見せかける。もうテスタビリティとか無視してざざっと書いてみた。<br />
<br />
時間がない中で、わけの分からんことを始めたので、方針はブレるしで、ひどいコードだが、考え方自体は気に入ってます。<br />
<br />
ただ、このまま機能を追加してゆき、コードや複雑性が増えてゆき、結局FWモデル自体がフレームワーク化してしまうという未来が見えなくもないですが。asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-69562199555195001022013-12-29T10:35:00.003+09:002014-01-18T08:30:37.601+09:002013年を振り返って年の瀬なので今年を振り返ってみる。<br />
年内中に書けそうだ。<br />
<br />
<a href="http://wsjp.blogspot.jp/2013/01/blog-post.html">今年の抱負は「アウトプットを増やす」</a>だった。<br />
<br />
結果は、<br />
<a href="http://wsjp.blogspot.jp/search?updated-min=2013-01-01T00:00:00%2B09:00&updated-max=2014-01-01T00:00:00%2B09:00&max-results=15">2013</a> (15) ←今年!<br /><a href="http://wsjp.blogspot.jp/search?updated-min=2012-01-01T00:00:00%2B09:00&updated-max=2013-01-01T00:00:00%2B09:00&max-results=40">2012</a> (40)<br /><a href="http://wsjp.blogspot.jp/search?updated-min=2011-01-01T00:00:00%2B09:00&updated-max=2012-01-01T00:00:00%2B09:00&max-results=23">2011</a> (23)<br /><a href="http://wsjp.blogspot.jp/search?updated-min=2010-01-01T00:00:00%2B09:00&updated-max=2011-01-01T00:00:00%2B09:00&max-results=41">2010</a> (41)<br /><a href="http://wsjp.blogspot.jp/search?updated-min=2009-01-01T00:00:00%2B09:00&updated-max=2010-01-01T00:00:00%2B09:00&max-results=22">2009</a> (22)<br />
<br />
と減ってしまいました。<br />
<br />
ブログは減ったが、増えたのがgithubのプロジェクト。<br />
とうとうフルスタック可能な<a href="http://wsjp.blogspot.jp/2013/09/wscore1.html">WScoreフレームワークを作ってしまいました</a>。<br />
<br />
作成は楽して、学ぶことが多かった一方、<br />
自分の知識の無さを実感もしました。<br />
<br />
大学も機械工学、卒業後の10年はほぼマネージャー、プログラマーになってからは一人での開発がほとんどだったので、よくて知識が偏っている感じ。はっきり言えば知識不足。<br />
<br />
だからか人と会話をする際に、自分の考えを正確に説明できない。まぁツイッターで絡んでも、今ひとつ相手の内容が理解できてないので、こちらも色々と書き込めないことが多かった。やはり網羅的な知識を一度は頭に入れたいと思うようになった。<br />
<br />
これが来年の課題かなと考えている。<br />
<br />asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-74749316220118615992013-12-20T20:42:00.005+09:002014-01-18T08:30:37.609+09:00「寄付」は英語でDonationかContribution?ちょっと英訳をしていて。<br />
<br />
英語で寄付といえば「Donation」とばかり思ってたが、<br />
「Contribution」という言い方もあると知った。<br />
<a href="http://ejje.weblio.jp/content/%E5%AF%84%E4%BB%98">http://ejje.weblio.jp/content/寄付</a><br />
<br />
何が違うのだろう?<br />
と調べてみたら、<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">Donation refers to a gift to a charitable organization whereas a contribution is generally associated with a gift to a common fund or collection.</span></blockquote>
<div>
<br /></div>
つまり<b>「Donation」は慈善団体に寄付するとき</b>に使い、<br />
<div>
それ以外の組織に対する寄付の場合は「Contribution」になると。</div>
<div>
<br /></div>
<div>
<span style="color: #0000ee; text-decoration: underline;"><a href="http://www.usingenglish.com/forum/ask-teacher/63524-contribution-vs-donation.html">http://www.usingenglish.com/forum/ask-teacher/63524-contribution-vs-donation.html</a></span></div>
<div>
<span style="color: #0000ee; text-decoration: underline;"><br /></span></div>
<div>
<a href="http://dictionary.reference.com/browse/donation">Dictionary.comで「Donation」調べてみた</a>が、はっきりとは書いてないなぁ。DonationはContributionでもあると書いてあるし。</div>
<div>
<br /></div>
<div>
確かにContributionの方が広い意味があり、Donationのように善意を受け付けるというより自分たちに賛同する人の助けを(お金として)受け取る、という使い方になるのかもしれない。<br />
<br />
ということで、今回は「Contribution」を使うことにした。</div>
asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-74333732881745687012013-10-29T11:10:00.000+09:002014-01-18T08:30:37.605+09:00Marvericks上でVirtualBoxが不安定に。どうやらMacのOSをMarvericksにアップデートしたら、VirtualBoxが不安定になったようです。<br />
<br />
参考:<br />
<br />
<a href="https://forums.virtualbox.org/viewtopic.php?f=8&t=58058">https://forums.virtualbox.org/viewtopic.php?f=8&t=58058</a><br />
<a href="http://blog.offline-net.com/2013/10/27/virtualbox-mavericks-update-error/">http://blog.offline-net.com/2013/10/27/virtualbox-mavericks-update-error/</a><br />
<br />
■症状は、<br />
<br />
VirtualBoxを走らせた後、仮想マシーン(VM)を立ち上げようとすると<br />
<div style="border: 0px; margin-bottom: 24px; padding: 0px; vertical-align: baseline;">
<br /></div>
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">Kernel driver not installed (rc=1908)<br />Make sure the kernel module has been loaded successfully.</span></blockquote>
<br />
<div style="border: 0px; margin-bottom: 24px; padding: 0px; vertical-align: baseline;">
<br />
<span style="background-color: transparent; color: #333333; font-family: '\1b$B%a%$%j%*\1b(B', Meiryo, '\1b$B%R%i%.%N3Q%4\1b(B Pro W3', 'Hiragino Kaku Gothic Pro', HiraKakuPro-W3, '\1b$B#M#S\1b(B \1b$B#P%4%7%C%/\1b(B', 'MS PGothic', Arial, Helvetica, sans-serif; font-size: 16.363636016845703px; line-height: 23.99147605895996px;">とエラーメッセージが出てVMが立ち上がりません。</span></div>
<div>
■対応方法1</div>
<div>
<br /></div>
<div>
このエラーが出たら、VirtualBoxを再インストールするしかないようです。インストール作業は5分もかからないのですが、面倒です。</div>
<div>
<br /></div>
<div>
再びVMを立ち上げると、動きました。</div>
<div>
VMのイメージ自体は問題ないようです。</div>
<div>
よかった。</div>
<div>
<br /></div>
<div>
とは言え毎度再インストールは、本当に面倒です。</div>
<div>
<br /></div>
<div>
■対応方法2</div>
<div>
<br /></div>
<div>
原因は、マックのウィンドウの赤い「×ボタン」、名前なんて言うんでしょうね?を使うと問題が出るようです。つまり、VMが正しくシャットダウンされてない状態になるようです。</div>
<div>
<br /></div>
<div>
なので、*nix系であれば、</div>
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">sudo shutdown -h now</span></blockquote>
<div>
とコンソールからシャットダウンすれば問題ないようです。</div>
<div>
<br />
<span style="color: #b45f06;">【追記:2013/10/30】</span><br />
<span style="color: #b45f06;">本日また同じ問題が発生。どうやら、上記の対策では対応できないようです。残念。こうなると、↓ですか。</span><br />
<br /></div>
<div>
■Oracle様待ち</div>
<div>
<br /></div>
<div>
Marvericksに対応したVirtualBox修正版がリリースされるまで待つしかなさそう。</div>
<div>
<br /></div>
<div>
<br /></div>
asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com2tag:blogger.com,1999:blog-957690751924967735.post-33162863694937877922013-10-27T15:09:00.001+09:002014-01-18T08:30:22.493+09:00時代は「CYOFW」時代は「CYOFW」。<br />
BYOFWは「<a href="http://fabien.potencier.org/article/50/create-your-own-framework-on-top-of-the-symfony2-components-part-1">Create Your Own FrameWork</a>」の略ということで。<br />
<br />
自分が言ってるのではなくて、SymfonyやComposer、PSR-3、そしてBEAR.Sundayが何を達成しようとしているかを考えれば、この方向に未来があると思う。<br />
<br />
好みのコンポーネントを組み合わせて、自分のFWを作る。Laravel風も、FuelPHPだって、CodeIgniter風も作れるはず。<br />
<br />
<br />
■コンポーネントが輝く<br />
<div>
<br /></div>
<div>
そうなると、コンポーネントが競争し始めると思う。Smartyかtwigか、プレーンPHPのどれ使うか悩むよね、程度の話なんですが。</div>
<div>
<br /></div>
<div>
いまさらフレームワークを新しく作るより、キラリと光るコンポーネント作ったほうが使われる気がする。</div>
<div>
<br /></div>
<div>
全く新しい機能を提供できれば一番。</div>
<div>
それが難しくても、早い&小さい、あるいは、使いやすい、といった面で特徴を出せる方がいいのかなぁと。</div>
<div>
<br /></div>
<div>
理想のコンポーネントは、簡単で小さくて使いやすく、その上、必要になれば様々な機能を簡単に追加できる、なんていうことができれば文句はないだろう。</div>
<div>
<br /></div>
<div>
自分で言えばCenaは他にはないコンポーネント。</div>
<div>
と考えると、今後はCenaに集中すべきだろう。</div>
<div>
<br /></div>
<div>
一方、Requestやテンプレートは、今更作ってもと思う。<br />
<br />
<br />
■グルー(糊)をどうするか<br />
<br />
コンポーネント間をつなぐのがグル〜、つまり糊なのだけれど、コンポーネント間、あるいはコンポーネント内の依存性は、どう解決すべきなのだろう。</div>
<div>
<br /></div>
<div>
DI対応しているのが前提で、コンテナをどうするのか?</div>
<div>
JSR-330のように、PHPでのDIの仕方も標準化されるのだろうと思う。</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
■FWってなんだろう?<br />
<br />
CYOFWとなると、FWってなんだろうと思う。<br />
さすがに全てのPHPerがFW自作するとも思えないので、有名なFWを使うという状態は変わらないと思う。なので、あまり意味のない疑問かもしれないが。<br />
<br />
何を持ってFWというのか?<br />
何がSymfonyで、どこからSilexになるのだろう。<br />
<br />
FWがアップデートしても、それまで書いたものが無駄にならない、というのがFWを特定するものだとすると、<br />
<br />
<ul>
<li>設定の仕方・手順、</li>
<li>MVの分け方(コントローラーの書き方)、</li>
</ul>
<br />
あたりがFWの肝になるのかな。</div>
asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-38882025415729453232013-10-27T13:50:00.002+09:002014-01-18T08:30:22.504+09:00WScore:逡巡(2013年10月)先月、「<a href="http://wsjp.blogspot.jp/2013/09/wscore20139.html">展望</a>」というエントリを書いていて、<div>
今「逡巡」してるということで、迷走中です。<br /><div>
<br /></div>
<div>
せっかく作った自作<a href="https://github.com/asaokamei/WScore-dev">WScoreフレームワーク</a>。</div>
<div>
<br /></div>
<div>
<br />勉強のためという言い訳で、<a href="https://github.com/asaokamei/WScore.Http">Http</a>、<a href="https://github.com/asaokamei/WScore.Web">Router</a>、<a href="https://github.com/asaokamei/WScore.Template">Template</a>まで作ってしまった。全部で1万5千行ぐらいとはいえ、仕事の合間に自分ですべてをメンテナンスするのは無理だなぁと。</div>
<div>
<br /></div>
<div>
少なくとも、今の全自作から少しずつ良さげなコンポーネントに入れ替えてゆくべきだろう。</div>
<div>
<br /></div>
<div>
そもそも自作FWにこだわる必要はあるのか?</div>
<div>
SymfonyやfuelPHPなど、有名&確実なFW使えばいいのでは?</div>
<div>
<br /></div>
<div>
そんなことを思っては逡巡する最近。<br /></div>
<div>
<br /></div>
</div>
asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-34186864222839684902013-09-24T12:03:00.000+09:002014-01-18T08:30:22.497+09:00WScore:展望(2013年9月)WScoreフレームワークの開発方向について、考えてみる。<br />
<br />
<b>1)現状のスタイルを踏襲する</b><br />
<br />
一番無難。<br />
また新しいことを試すのも楽。<br />
<br />
なので、WScoreの開発は続けてゆくと思う。<br />
DIをどうするか(Ray.DIに乗り換えるか)など、結構基本的な部分で悩みがあるのだけど、そういうのも含めて、自分の勉強のためになると思っている。<br />
<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;">本音を言えば、最初はフルスタック可能なフレームワークを作る気はなかった。それが、</span><span style="font-size: x-small;">勉強のためという理由で自分で開発したり</span><span style="font-size: x-small;">、100行ぐらいでできそうかも、と思ってしまったとかで、機能が膨れ上がっていった。</span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;">でもコード量は1万5千行ぐらいと比較的小さめなFWだと思う。</span></blockquote>
<br />
<br />
<b>2)Cena on Doctrine 2</b><br />
<br />
Cena技術は、本来どんなORMの「薄いマッパー」として動く、はず。<br />
なのでDoctrine 2上でCenaを開発してみたい。<br />
<br />
実は、これを最初に検討した。<br />
エンティティの状態が知りたいので、UnitOfWorkの3000行のコードを見ているうちに、気がついたらwsCoreというレポジトリをgithubで作っていたのだった…<br />
<div>
<br /></div>
<div>
あれからDataMapperやCenaについての知識も増えたし、もう一度試してみたいと思う。</div>
<div>
<br /></div>
<blockquote class="tr_bq">
<span style="font-size: x-small;">もう一度Doctrineのコードを見たら、「getEntityState」というメソッドを発見。これを使えば楽に作れる気がしてきた。どうして一年前に見つからなかったのか謎ではあるが。</span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;">でも、Cena on Doctrineができたら、WScoreを使ってくれる人はいなくなるなぁ、と思いつつ、どちらにしろ使ってくれる人は殆どいないと思うので、これが正しい道だと思う。</span></blockquote>
<br />
<br />
<b>3)クライアント側の開発(JavaScript)</b><br />
<br />
クライアント側のライブラリを開発する。<br />
つまりJavaScriptを書くということ。<br />
<br />
前にCena-DTAというのを作ったことがある。<br />
初めての本格的JS開発ということで、jQueryのプラグインとして開発したので、複雑な動きに対応しづらくて大変だった。また当時はWebSqlしか使えなかったので、SQLを使って作った。<br />
<br />
今ならBackboneかAngularを利用して、モデルか何かのプラグインみたいな形で開発してみたい。それとIndexed Databaseを使ってみたい。<br />
<br />
<br />
<b>4)XaaS</b><br />
<br />
開発は楽しいのだけど、世界はすごいスピードで進んでいる。<br />
BaaS(Backbone As a Service)など、こういうところでCenaを使ってほしいと思ってたレイヤーがサービス化している。<br />
<br />
今のペースで間に合うような気はしないが、何かはしてみたい。<br />
<br />asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-42853112639583992182013-09-19T14:32:00.004+09:002014-01-18T08:30:22.508+09:00WScore:フレームワークを自作する理由わざわざフレームワークを自作するのはなぜか?<br />
なぜ面倒なフレームワークづくりを続けられるのか?<br />
<br />
フレームワークの自作は大変なだけで、既存のものを使うか利用するほうがはるかに楽だと思います。大体動くところまではできますが、細かなバグを見つけたり、きちんとテストを書くのは大変な作業です。<br />
<br />
<br />
自分の場合は、明確な理由が一つ。<br />
<br />
Cenaデータ転送という技術を思いついてしまったたから。<br />
ハマりすぎて特許まで取得してしまった。<br />
<br />
これで何ができるのか見てみたい。<br />
そして周りにデモを見せたい。<br />
<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;">ちなみに<a href="http://www.workspot.jp/cena/ja/">こんなサイトでCenaについて</a>書いています。</span></blockquote>
<br />
世界で唯一の技術<span style="font-size: x-small;">(かもしれない)</span>と思うと、不思議とやる気が湧いてきて、開発を続けています。高揚と幻滅を繰り返しながら、少しずつ機能を追加してゆく作業は、なかなか楽しいです。<br />
<br />
<br />
もちろん、他にも理由はあります。<br />
<br />
まずは、<b>勉強のため</b>、というのがあります。<br />
<br />
例えばDIコンテナとはなにか?<br />
実際に作って、そして使ってみることで理解できた気がします。<br />
<br />
やはりフレームワークを作るとなると、いろいろなデザインパターンを使う場面が増えてきます。そういう意味で、自分のプログラミング能力を伸ばすのに最適な気がします。<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;">もっとも勉強なら、既存のフレームワークを使って何かサービスを立ち上げるほうが広い範囲の技術を覚えられるので、フレームワーク自作よりおすすめな気がする。</span></blockquote>
<br />
<br />
<b>自分の仕事のためのライブラリづくり。</b><br />
<br />
自分の思い通りに動くのは気持ちがいい。<br />
<br />
と言うのはありますが、大事なのはサポート期間が無期限なこと。<br />
これがメリットなのか、大変なだけなのかはわかりませんが。<br />
<br />
SymfonyのLTSが3年と聞いて、短いなと感じました。<br />
自分の仕事だと、ほとんどは5年以上動いている。最長で10年のプロジェクトがあるので、サポート期間としては5年ぐらいはほしいところ。<br />
<br />
他の人はどうしてるのだろう?<br />
まぁサポート期間が切れて動かなくなることはないし、そんなに気にしなくてもいいのかな?<br />
<div>
<br /></div>
正しく作れば、サイトのコアとなるドメインコードはフレームワークから独立するので大丈夫、となるのだろうか?<br />
<br />asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-35325073425078536062013-09-17T14:45:00.002+09:002014-01-18T08:30:22.501+09:00WScore開発を始めてから1年。ふとgithubを見返したら、wsCoreの最初のコミットが2012年9月5日。<br />
早いもので、開発を始めてから1年が経過した。<br />
<br />
その後2月頃にcomposerを使ったコンポーネントベースに移行。<br />
また名前もWScore.*に変更。<br />
「*」は、各コンポーネントの名前。<br />
<br />
特徴は:<br />
・Cenaデータ転送技術がある!<br />
・コンポーネント・ベースでフルスタック可能、<br />
・小さい(16,000行ぐらい)、<br />
といったところ。<br />
<br />
開発の現状は、ほぼアルファぐらい。<br />
<br />
大まかな機能は実装できた。<br />
明らかなバグ・不具合もなし。<br />
ただテストは足りない。<br />
微妙に機能が足りてない(i18nなど)。<br />
<br />
今後は、細かな構成やAPIを調整したい(見返すと汗が出る箇所が幾つかある)ので、状況としてはアルファぐらいかなと思う。<br />
<br />
もう少しAPIを煮詰めてベータと言えるぐらいにはしたい。<br />
<br />asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0tag:blogger.com,1999:blog-957690751924967735.post-82493971351088708902013-02-28T15:06:00.001+09:002014-01-18T08:30:22.511+09:00php5.4のcliだけインストールphpのAuraというフレームワークがあるのを知った。<br />
<br />
BEAR.Sundayはすごいが、Auraはコードが綺麗。<br />
またコンポーネントが独立していて、他の依存性がない。<br />
ので、すごく追いかけやすい上に勉強になる。<br />
<br />
今までgithubでコードを見てたが、ぜひPhpStormで見たい。<br />
<br />
が、ちょっとした問題が。<br />
Auraはphp5.4必須で、今のPCはまだバージョンが5.3なので、インストールで失敗する。正確にはComposerが依存性をチェックしてくれるので、そこから先に進まない。<br />
<br />
そんなことを短くtwitしたら、すぐに教えてくれた。<br />
<br />
<a href="https://twitter.com/hidenorigoto/status/306970679943786496">https://twitter.com/hidenorigoto/status/306970679943786496</a><br />
<br />
ありがとうございました。<br />
<br />
しかし、どうやってphp5.4のcliを手に入れるんだ?<br />
自分でインストール?<br />
<br />
<h2>
php5.4のcliインストール</h2>
<br />
実は自分でphpをインストールしたことがなかった。<br />
<br />
ということでメモ。<br />
<br />
<b>1.php.netから最新tarballをダウンロード。</b><br />
<br />
そして下記のフォルダーに展開した。<br />
<blockquote class="tr_bq">
/usr/local/src/php-5.4.12</blockquote>
<br />
<b>2.configureを走らせる。</b><br />
<br />
<blockquote class="tr_bq">
./configure --prefix=/usr/local/src/php-5.4.12 --enable-mbstring --with-pear</blockquote>
すると色々足りないと怒られた。<br />
適当にapt-get。<br />
<br />
<blockquote class="tr_bq">
sudo apt-get install libxml2<br />sudo apt-get install xml2<br />sudo apt-get install libxml2-dev</blockquote>
<br />
多分、libxml2-devというのがUbuntuでは必要。ディストリビューションによって、少しずつ名前が違うみたい。<br />
<br />
またapx2を入れることが多いが、cliのみ作るのでバッサリ削除。<br />
<br />
<b>3.make</b><br />
<br />
通った。<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;">ちなみにmake installすると既存のphpを置き換えると思うので、走らせない。</span></blockquote>
<br />
<b>4.インストール</b><br />
<br />
自分でインストール。<br />
<br />
目的のcliバージョンのphpは<br />
/usr/local/src/php-5.4.12/sapi/cli/php<br />
<blockquote class="tr_bq">
cd /usr/local/bin<br />sudo ln -s /usr/local/src/php-5.4.12/sapi/cli/php php54</blockquote>
<b>5.Auraインストール</b><br />
<br />
Auraのどれをインストールするか悩んだが、これで。<br />
<blockquote class="tr_bq">
git clone https://github.com/auraphp/system.git<br />mv system/ Aura.system<br />cd Aura.system/<br />php54 composer.phar install</blockquote>
さらに、<br />
<blockquote class="tr_bq">
cd web/<br />php54 -S localhost:8080 index.php</blockquote>
でサーバーとしても動いたようです。<br />
<br />
ところでAuraのデモは「hello world」だけなのかな。<br />
う〜ん、インパクトが弱い。asaphttp://www.blogger.com/profile/06750655348597691983noreply@blogger.com0