表紙 編集 差分 一覧 最近 短縮 付箋 ログイン 凍結中

Picowa - Sinatra風 軽量 Web Application Framework

N2Wiki > Picowa

一覧 [非表示]

Sinatra風 軽量 Web Application Framework [PHP][Picowa]

Picowaについて

Picowa とは

Sinatra 風の軽量 Web アプリケーションフレームワークです。

特徴

  • Sinatra 風のルーティング
  • ルーティングと紐づく before / around / after フィルタ
  • コンポーネントの遅延ロード
  • 最小限の DI コンテナ

動作環境

PHP 5.2 以降

元になったもの

  • Fitzgerald (Sinatra 風軽量フレームワーク)
  • Blanka (anatoo氏のPHP5.3向け次世代フレームワーク)
  • Curry, Quotation ライブラリ等 anatoo氏の一連のエントリ
  • これらのソースコードを公開された作者の方々に感謝いたします。

Download

簡単なサンプル

Hello world

 $app = new Picowa;
 
 $app->get('/','hello');
 function hello() {
     return 'Hello world!';
 }
 
 $app->run();

ルート

 $app->get('/', 'func1');
 function func1() {
     // do something
 }
 
 $app->post('/', 'func2');
 function func2() {
     // do something
 }
  • Picowa クラスのオブジェクトがアプリケーションオブジェクトになります。
  • Picowa オブジェクトの get, post, put, delete メソッドが、各HTTPメソッドに対応します。
  • 最初の引数が URL マッチングパターン、2番目の引数にコールバックを渡します。
  • ルートは定義した順にマッチを行い、最初にマッチしたルートのコールバックが呼び出されます。
  • get, post で同一のコールバックを呼び出したい場合、以下のようにもかけます。
 $app->http('get|post', '/', 'func1');
  • または
 $app->http('*', '/', 'func1');

マッチングパターンとパラメータ

 $app->get('/hello/:name', 'hello');
 function hello($name) {
     return "Hello {$name}!";
 }
  • パラメータはマッチしたした順番にコールバックの引数として渡されます。
  • 第3引数にパラメータとパターンの配列を渡すことで、パラメータのマッチングパターンを指定できます。
 $app->get('/hello/:name', 'hello', array('name'=>'foo|bar'));
 function hello($name) {
     // $nameがfooまたはbarの場合のみこの関数は呼ばれます。
     return "Hello {$name}!";
 }
  • マッチングパターンには正規表現を使用できます。
 $app->get('/.*/:name', 'hello', array('name'=>'\w+'));

コールバック

  • Picowa クラスを継承し、そのメソッドをコールバックとして登録する場合。
 class Application extends Picowa {
     public function hello() {
         return 'Hello world!';
     }
 }
 $app = new Application;
 $app->get('/', $app->_hello());
 $app->run();
  • Pico クラスを継承したオブジェクトのメソッド名の前に _ を付けて呼び出すとそのメソッドのコールバックを取得できます。
  • Picowa クラスは Pico クラスを継承しているので、アンダースコア付き呼出でコールバックを取得できます。
  • Blanka フレームワークからのインスパイヤです。(^^;;
  • PHP5.3以降なら無名関数を使って以下のようにかけるはずです。
 $app->get('/', function () {
     return 'Hello world!';
 });

変数のバインド

 $app->get('/', bind('layout', $app));
 function layout($app) {
     return 'current layout: ' . $app->options()->layout;
 }
  • bind 関数にコールバックと変数を渡すと、変数の値が部分適用されたコールバックが返ります。
  • コールバックに対してアプリケーションオブジェクトなど渡すために使うことができます。
  • Pico クラスを継承したオブジェクトの場合には以下のようにして、部分適用されたメソッドのコールバックを取得できます。
 class Application extends Picowa {
     public function hello($name) {
         return 'Hello {$name}!';
     }
 }
 $app = new Application;
 $app->get('/', $app->_hello('picowa'));
 $app->run();
  • メソッドのコールバックを取得する呼出の引数にbindしたい値を渡すことで部分適用されたコールバックが返ります。
  • パラメータと組み合わせる場合、以下のように、bindした引数、パラメータの順にコールバックに渡されます。
 class Application extends Picowa {
     public function hello($bind1, $bind2, $param1, $param2) {
         return 'Hello {$bind1},{$bind2},{$param1},{$param2}!';
     }
 }
 $app->get('/:param1/:param2', $app->_hello($bind1, $bind2));

View

 $app->get('/', bind('hello', $app));
 function hello($app) {
     // _pico/views/hello.php をincludeし出力
     return $app->render('hello');
 }
  • viewファイルは素のPHPです。
  • テンプレートエンジンは持っていません。お好きなものをお使いください。

フィルタ

before フィルタ
 class Application extends Picowa {
     public function hello($name) {
         return "Hello {$name}!";
     }
     public function debuglog($args) {
         var_dump($args);
     }
 }
 $app = new Application;
 $app->get('/:name', $app->_hello(), array('name'=>'Jon|Ponch'));
 $app->before('get','/:name', $app->_debuglog(), array('name'=>'Jon|Ponch'));
 $app->run();
  • ルート設定と同様なマッチングパターンが使用できます。
 class Application extends Picowa {
     public function hello($name) {
         return "Hello {$name}";	
     }
     public function beforeFilter($args) {
         $args[0] .= ' さん';
         return $args;	
     }
 }
 $app = new Application;
 $app->get('/:name', $app->_hello());
 $app->before('get', '/:name', $app->_beforeFilter());
 $app->run();
  • パラメータは配列としてフィルタに渡されます。
  • 配列を返せばパラメータを書き換えることができます。
after フィルタ
 $app = new Picowa;	
 $app->get('/','hello');
 $app->get('/ja/','hello');
 function hello() {
     return 'Hello world!';
 }
 $app->after('get','/ja/','translate');
 function translate($text) {
     return strtr($text, array('Hello'=>'こんにちは','world'=>'世界'));
 }
 $app->run();
  • Viewファイルの出力が文字列として渡されます。
  • 書き換えて文字列を返すことでViewの出力を変更できます。
aroundフィルタ
 class Application extends Picowa {
     public function hello($name) {
         return "Hello {$name}";    
     }
     public function aroundFilter($fn, $args) {
         $args[0] .= ' さん';
         return '*** '.apply($fn, $args).' ***';    
     }
 }
 
 $app = new Application;
 $app->get('/:name', $app->_hello());
 $app->around('get', '/:name', $app->_aroundFilter());
 $app->run();
  • 最初の引数にはコールバック、二つめの引数にはコールバックに渡すべきパラメタが配列で渡されます。
  • afterフィルタと同様出力文字列を返します。

コンポーネント

  • Picowaは機能拡張、再利用の単位としてコンポーネントと呼ぶ仕組みのみを提供します。
  • コンポーネントは他のオブジェクトに公開属性でコンポジションされるオブジェクトです。
コンポーネントの利用
 class Application extends Picowa {
     public $uses = array(
         'ComponentClassName'
     );
 }
 $app = new Application;
 $app->ComponentClassName->someMethod();
  • PicoまたはPicowaクラスを継承したクラスでusesインスタンス変数の初期値にコンポーネントクラス名の配列を設定します。
  • コンポーネントクラスの名前以外でアクセスしたい場合は以下のようにします。
 class Application extends Picowa {
     public $uses = array(
         'aliasName' => 'ComponentClassName'
     );
 }
 $app = new Application;
 $app->aliasName->someMethod();
  • コンポーネントのコンストラクタに静的なパラメータを渡す場合は以下のようにします。
 class Application extends Picowa {
     public $uses = array(
         'aliasName' => array(
             'ComponentClassName', 'param1', 'param2'
         )
     );
 }
  • オブジェクトに動的にコンポーネントを追加する場合は以下のようにします。
 $app = new Picowa;
 $app->attach('aliasName', array('ComponentClassName', $param1, $param2));
コンポーネントの作成
  • _lib, _pico/app, _pico/libs にPEAR式命名法に則って配置されたクラスファイルがコンポーネントとして利用できます。
  • コンポーネントクラスは利用時にautoloadされます。
  • コンポーネントクラスが満たすべきインターフェースは特にありません。
  • コンポーネントクラス中でコンポーネントを使用する場合、以下のようにPicoクラスを継承します。
 class MyComponent extends Pico {
     public $uses = array(
         'ComponentClassName'
     );
 }
遅延読み込み
  • コンポーネントクラスの読み込みとインスタンスの生成は、最初のコンポーネントプロパティへのアクセスが起こるまで遅延されます。
 class Application extends Picowa {
     public $uses = array('Foo');
 }
 $app = new Application;    // まだFooのクラスファイルは読み込まれない。
 $component = $app->Foo;    // クラスファイルがautoloadされ、インスタンスが生成する。
遅延プロパティアクセス
  • コンポーネントがPicoクラスを継承している場合、コンポーネントオブジェクトのプロパティアクセスやメソッド呼び出しが実際に起こるまで、コンポーネントクラスの読み込みとインスタンス生成を遅延させることができます。
  • アンダースコア付きアクセスを行うことで遅延プロパティアクセスのためのプロミスオブジェクトを取得します。
 class Application extends Picowa {
     public $uses = array('Foo');
 }
 $app = new Application;    // まだFooのクラスファイルは読み込まれない。
 $promise = $app->_Foo;     // まだFooのクラスファイルは読み込まれない。
 $promise->someMethod();    // クラスファイルが読み込まれ、FooオブジェクトのsomeMethodを呼び出す。
遅延メソッドコールバック取得
  • 遅延プロパティアクセスとメソッドコールバック取得のアンダースコア付き呼び出しを組み合わせることで、メソッドコールバックが実際に呼び出されるまで、コンポーネントクラスの読み込みとインスタンス生成を遅延させることができます。
 class Application extends Picowa {
     public $uses = array('Foo');
 }
 $app = new Application;    // まだFooのクラスファイルは読み込まれない。
 $promise = $app->_Foo;     // まだFooのクラスファイルは読み込まれない。
 $callback = $promise->_someMethod();    // まだFooのクラスファイルは読み込まれない。
 call($callback);           // クラスファイルが読み込まれ、FooオブジェクトのsomeMethodを呼び出す。
  • いずれの場合も2回目以降のアクセスは通常のプロパティへのアクセスとなります。
  • Picowaではルートに紐付けるコールバックを遅延メソッドコールバックにすることで、使用しない余分なクラスファイルの読み込みを省略できます。
 $app->get('/foo', $app->_Foo->_someMethod());
  • 上の例では/fooへのアクセスがある場合にだけ、Fooのクラスファイルが読み込まれます。
リファラ: