読者です 読者をやめる 読者になる 読者になる

Piece FrameworkはRESTに対応しうるか?

PHP

Piece Frameworkをつかって、Tropyクローンを作りました。まだ、いろいろ実験中なので、もう少し安定してからソースを公開したいと思います。


Piece Frameworkに初めて出会ったときに、こういうことができるなと予想していたことが幾つかあったのですが、Tropyを作成している過程で、当たっていた予想と当たっていない予想があることに気づいてきました。


まず、当たっていた予想としては、「Pieceを使ったアプリケーションでは、プレゼンテーション層を他のレイヤーから完全に分離できる」ということ。
これは先日のエントリで紹介したように、独自レンダラを使えば、全く同じビジネスロジックで、プレゼンテーションだけを変更することができるわけです。
HTMLでも、JSON、XMLでも簡単に出力を変更することができるので、Tropyを例にとると、Ajaxによるランダムなページの表示や、スライドショーモードの追加といったことを簡単に実現できました。
すなわち、Piece Frameworkでは、出力に対しては透過的な変更ができるというわけです。


ところが、出力に対して行えた透過的な変更が、入力に対しても行えるかというと、ちょっとどうかな、というのが今の実感です。これは予想に反していました。
具体的に述べると、Tropy REST APIというのを考えているのですが、これをPiece Frameworkを使って実装するのは難しいです。


ここでいうTropy REST APIというのは、HTTPメソッドを使って、

  • GETでランダムなページを取得
  • POSTで新規ページを作成
  • PUTで既存のページを更新
  • DELETEは該当操作なし(オリジナルのTropyにDeleteが存在しないので)。

というような操作を提供するAPIです。


いろいろ考えた挙げ句、Pieceの継続サーバの初期状態を使い、

initial:
  class: TropyRestAction
  method: handleRest
#...

というフローを用意して、TropyRestActionクラスのhandleRestメソッドの中で、

class TropyRestAction extends Piece_Flow_Action
{
    function handleRest() {
        switch($_SERVER['REQUEST_METHOD']) {
        case 'GET':
            return 'processGET';
        case 'POST':
            return 'processPOST';
        case 'PUT':
            return 'processPUT';
        default:
            return 'not_found';
        }
    }
}

というように、HTTPメッソドに応じて次の状態へ遷移させよう、という一応の結論に達しました。


スーパーグローバル変数にアクセスしなくてはならないのが、多少いやな感じです。
これは、まあ、現時点での限定的な問題なので、我慢して当初の目論見通りフローを設計します。そうすると、確かにGETとPOSTに関しては、同じビジネスロジックを再利用した上で、REST APIを実装することができました。


しかし、PUTに関しては、Piece_Unity_RequestやPiece_Rightの実装上の制限で、フレームワーク内で上手く扱えません。
無理矢理実装しようとすると、どうしてもアドホックな実装になってしまい、他のコンポーネントとの一貫性を完全に欠いてしまいます。


HTTP PUTメソッドについては、PHPにおいてGET, POST以外のメソッドを扱う難しさもあって、フレームワーク云々以前の問題かもしれません。
そもそも、RESTによるWebサービスをPHPで利用するという話は聞いたことがあっても、PHPでRESTによるWebサービスをPHPで提供するという話はあまり聞いたことがありません。
とはいえ、現実の問題に簡易な手段を提供するのが、フレームワークの役割というものなので、これついてはもっと考えてみたいと思います。(Piece_Unity_Requestに少し手を入れた上で、GET, POST以外のメソッドをPiece_Rightで扱えるように変換するインタセプタを用意すれば、もしかしたら簡単に実現できるかもしれません。)