2012年1月31日火曜日

AmidaMVC:ComponentとAction

AmidaMVCが何をしているのか?

一言で言えば、コンポーネント(部品)を次々と実行するだけ。
格好良くコンポーネントと言ってますが、要するにクラスです。

コンポーネントの登録

たとえば、こんなコードです。


// Controllerを作成、
$ctrl = new \AmidaMVC\Framework\Controller();
// コンポーネントを追加。
$ctrl
    ->addComponent( 'Config', 'config' )
    ->addComponent( 'Router', 'router' )
    ->addComponent( 'Loader', 'loader' )
    ->addComponent( 'Render', 'render' )
;
// フレームワーク実行
$data = new \AmidaMVC\Component\SiteObj();
$ctrl->start( $data );

最初にSiteObjとControllerのオブジェクトを作成してから、
コントローラーにコンポーネントを追加してゆきます。

これらのコンポーネントを順番に実行してゆきます。

クラスなので、実際に走らせるにはメソード名が必要です。
最初は「actionDefault」というメソードを呼び続けます。つまり正常に動いている場合の処理をこのメソード内に書きます。

上の例だと、
・Config:設定用クラス。必要そうな値を設定。
・Router:URLから読み込むファイルを決定する。
・Loader:見つけたファイルを読み込む。
・Render:テンプレートを呼び出してHTMLを出力する。
という処理を順番に行います。

アクション

実行するメソード名は、アクションと読んでいます。
実際はactionAction、最初に「action」をつけて呼び出します。
例えばactionHelloとかです。

もしアクションが存在しない場合。
デフォルトのアクション「Default」を呼び出します。
つまり「actionDefault」のメソードが呼ばれます。

エラー処理の例

途中でエラーが起きたとします。
たとえばRouterでファイルがみつからなかった場合について考えてみます。
  • Routerでファイルがみつからない。
    この場合、Routerはアクションを「_PageNotFound」に変えて、次のコンポーネントに処理を渡します。
  • これ以降、「_PageNotFound」が呼び出されます。無ければデフォルトのアクションを実行します。
  • さて、Loaderの「_PageNotFound」のアクションでは、設定で指定していたファイル(PageNotFound.md)を読み込みます。
    この時点で、表示に必要なデータはそろったことになるので、正常系に戻します。つまり「actionDefault」を呼ぶようにコントローラーに命令します。
  • Renderはファイルが読み込まれているので、正常系の処理と同じになります。
とまぁ、こんな感じで、エラーがあった場合に異常系の処理をして、処理が終われば正常系の処理に戻したりが出来ます。これでフレームワークの設計が簡単になるんじゃないかと思った訳です。

2012年1月30日月曜日

AmidaMVC:今更PHPマイクロフレームワーク作ってみた

ちょこちょこ書いてますが、PHPのmicroframework作ってみました。
今更の感覚が強いですが、
  • 勉強のため、
と思って作ってみました。

でも勉強のためだけで作ることは無かったですね。
実は
  • アミダ式Dispatcher(と勝手に命名)
というロジックを思いついてしまって。
それをMVCフレームワークに応用したら面白そうだなと思ったら、作ってみたくて仕方がなくなり作ったという次第です。

ウェブサイトを作っていて、面倒なのがエラー処理。
ページが見つからないなどの処理をきれいに行いたいと思ってました。

アミダ式の説明は後で行いますが、
標準の処理が簡単なだけでなく、エラーなどの異常系の処理も簡単にできるのではないかと思っています。
まぁ自分が初めて考えついたロジックとは思いませんし、誰かがMVCに応用していてもおかしくはない、というか実はこれがMVCの標準的な処理だった、なんてオチはないといいのですが。こういうのは広い知識を持ってないのがつらいところです。

◆特徴は?

せっかく作ったので、何か特徴があるはず…
  • モデルやビューが無くても動く。
    一つのファイルにPHPとHTMLが混在していても、ちゃんとテンプレート内に入るようになります。もちろんクラスを作っても大丈夫。
  • ルートを設定してもしなくても動く。
  • ファイルビューワーとして、マークダウンファイルやテキストファイルをHTMLとして表示することが出来ます。PHPファイルもソースコードとして表示できたりします。
  • ファイルシステムがベース
    特徴なのかどうか分かりませんがデータベースは必要ありません。遅いと思いがちなファイルですが、今後SSDが普及するにつれ十分なスピードが出るようになるのではないでしょうか?すると簡単にファイルで作れるフレームワークも便利かなぁと。
その他、ファイルを直接修正したりすることも(多分簡単に)出来るはずなのですが、こうなるとフレームワークなのかCMSなのか分からなくなるので、適当なところで切り上げないと。

2012年1月17日火曜日

クロージャーを使ったPSR-0準拠のクラスローダー

PSR-0をベースにしたクラスローダーを探したのですが、全てクラスベースのクラスローダーしか見つかりませんでした。でコピーするのが面倒だったので、クロージャーを使ったクラスローダー作ってみました。
こういうのにクロージャーって便利なんですね。
初めてクロージャーをちゃんと使った気がする。
ソースコードはgitHubのGistにて公開しました。
https://gist.github.com/1620960#file_class_loader_ns.php


特徴は、パラメータ無しで動きます。

◆使い方は、たとえば次のようなクラスをロードする場合。
new AmidaMVC\Folder\SomeClass();

対応するクラスのが次の場所だったとします。
pathto/src/AmidaMVC/Folder/SomeClass.class

こういう場合は、pathto/src/AmidaMVC/bootstrap.php
などに上のGistコードを貼り付けてください。

spl_autoload_register( ClassLoader() );
普通、多分、他のコードを見る感じだとクラスをロードするには、ライブラリで使っているネームスペースとパスを指定する必要があります。
この関数は、呼ばれた場所がライブラリの一番上と仮定して、現在のフォルダーをネームスペース(例の場合はAmidaMVC)、そして現在のフォルダーをのぞいたパス(例の場合はpathto/src/)を設定します。

◆ただし、関数の定義が別ファイルにある場合は、先のbootstrap.phpで

spl_autoload_register( ClassLoader( __DIR__ ) );

とすれば動く「はず」です(動作は未確認)。

◆注意

今コードを見たら、バグがありますね。
少なくとも自分の環境では動いているので、ちょっと修正すれば動くと思います。また時間を見つけたら修正します。

2012年1月11日水曜日

[PHP] Chain of Reponsibility (CoR)を使ったDispatcher

なぜかChain of Reponsibility (CoR)を使ったDispatcherをPHPで書いている。今、必要なこととも思えないが、一度始めたら見切りを付けるまで頭から離れない。仕方ないので書いている感じ。

そもそもは、Html5のローカルアプリ開発にJavaScriptのMVCいるよね、という話から始まって、Mediatorパターンいいよと言われたところからスタートした気がする。

で、JavaScriptの簡易MVC・フレームワークを探したら…
簡単に見つかる。
で、コードを読んでも追いかけられない。
モデルが既に存在しているので、Cenaをそのまま使えない。

じゃあ自分で書いてみるか、となって、
MVCを勉強することにした。


MVCモデルって、要はリクエスト(httpの要求ですね)をもとに、
処理するルーチン(関数でもクラスでも)を決めるだけだよね?
それってなんて言うDispatch?
だからDispatchを書き始めた。

◆車輪の再発明だけど

書いているうちに、簡単なのだと使いづらいと思い始めた。
実際にデータを読み込むところをモデルと考えた場合、
その前後にたくさんの処理が必要になる。

例えば認証、キャッシュ。
認証でエラーがあればモデルなんか読み込む必要がない。
キャッシュにヒットすれば、これまたモデルを読み込む必要がない。
一方、モデルの処理中に致命的エラーが起きたら、まったく別の画面に飛ばす場合もあるでしょう。
で、全部OKだったら、読み込んだデータをHTMLに直す処理を始められる。

つまり途中で処理をかえる必要がある。
思ったより、複雑。

◆CoR

で、CoRを使ってみることにした。
これしか使えそうなパターンを知らなかったからだけど、symfonyやstrutsでも使われてるとどこかで読んだので間違った選択ではなかったみたい。

と、この辺りで気づいたのは、
リクエストから処理するルーチンをDispatchする部分(Router)と、
実際に処理を行うルーチンでのDispatchする部分(なんて言うんだ?)と、
別の話だなと。


2012年1月6日金曜日

2012年の抱負

おめでとうございます。
2012年(平成24年)が明けました。

せっかくなので今年の抱負を書きます。

アウトプットを増やす

もともと書くのは遅いと思うので、今年は余り推敲せずに書くことにして、アウトプットを増やしてみたいです。

もう上の一行で何度も推敲してますがw

Cena-DTAを何とかする

ひとまず日本での特許を取得。
今はアメリカで特許の出願済み、まだ取得は出来てません。

今年はCena-DTAを広める動きをしたいです。

また、コーディングも「着々と」進める予定。

ちゃんと仕事する

今まで適当に仕事をしてきたわけではないのですが。

つい後回しにする悪い癖があるので、今年は頑張りたいです。請求書をちゃんと書く、とかですかね。

それと、受注した仕事が中心だったので、今年は少し能動的に仕事したいです。というかCena-DTAに力を入れてみたいです。

個人的なその他の目標

家族サービスは今までどおり(むしろ増やしたい)
勉強会を月2回ぐらい参加する(家族との協議が必要)
体重を5kgぐらい減らす(減らしすぎないようにするw
東日本大震災を受けて

今年の抱負を考えるにあたり、忘れられないのが東日本大震災。
家族・親戚で直接的な被害をこうむってはいませんが、

「今まで通りでは駄目だ」

という思いをいっそう強くしました。
一昨年のリーマンショック以来感じてたことでもあります。

まだ大きな地震が来るという予想もあります。
いろんなことを見直して、しっかりと生き延びてゆきたいです。