PHPでRESTサーバを書きたくなった場合、F.Wならそれの下地はあるだろうけどそれ程でも…っていう場合など。
Luracast/Restler
日本語の記事は見つからなかったけど、このライブラリが鉄板っぽいので使ってみる。
https://github.com/Luracast/Restler
以下、下記の記事を参考にする。
https://github.com/Luracast/Restler/blob/master/README.md
インストール
composer.pharのあるディレクトリで下記のコマンドを実行。
$php composer.phar create-project luracast/restler {projectName}
で{projectName}のディレクトリができて、その中にインストールされる。
illuminate/viewがバージョンで蹴られた。。。
PHP5.3というのバージョンのせいで蹴られる。Restler自体はこの記事時点で5.3.2あればOKなんだけど。
reated project in example_rest Loading composer repositories with package information Installing dependencies (including require-dev) Your requirements could not be resolved to an installable set of packages.
Problem 1 - illuminate/view v4.2.9 requires php >=5.4.0 -> your PHP version (5.3.3) or "config.platform.php" value does not satisfy that requirement. .... << などと言われる。ので、
"require":{ "php":">=5.3.0" }, "require-dev":{ "luracast/explorer":"*", "guzzle/guzzle":"~3.1.1", "behat/behat":"2.5.*@stable", "rodneyrehm/plist":"dev-master", "zendframework/zendamf":"dev-master", "symfony/yaml":"*", "mustache/mustache": "dev-master", "twig/twig": "v1.13.0", "illuminate/view": "4.2.*", "bshaffer/oauth2-server-php":"v1.0" },
とあるのを
"provide":{ "illuminate/view": "4.2.*", } "require":{ "php":">=5.3.0" }, "require-dev":{ "luracast/explorer":"*", "guzzle/guzzle":"~3.1.1", "behat/behat":"2.5.*@stable", "rodneyrehm/plist":"dev-master", "zendframework/zendamf":"dev-master", "symfony/yaml":"*", "mustache/mustache": "dev-master", "twig/twig": "v1.13.0", "bshaffer/oauth2-server-php":"v1.0" },
としてとりあえず回避。
サンプル&テスト
インストールディレクトリ内に、publicフォルダがあるのでそれをDocumentRoot配下にシンボリックリンク。
http://example.com/public/examples/index.html
http://example.com/public/tests/param/explorer/index.html
http://example.com/public/tests/request_data/explorer/index.html
がサンプル&テストとして使えるようになる。
後はだいたいこれ見ればわかるでしょう・・・・という感じで。
とりあえずベースとして
<?php require_once 'vendor/restler.php'; use Luracast\Restler\Restler; $r = new Restler(); $r->addAPIClass('Example'); // repeat for more $r->handle();
で、ここに後はaddAPIClassでどんどんと加えていく。
クラスの定義を2段階にしたいと思って
index.php
<?php $r->addAPIClass('foo\Example2'); // repeat for more
foo/Example2.php
<?php namespace foo; class Example2{ function hello($to = "World", $from = "Me"){ return "Hello $to! From $from ?"; } }
とすると、
http://example.com/rest/example2/hello
が使える。
GETメソッド
クラスの各メソッドにHTTPメソッドのプレフィクスを付けるのが決まり。ただ、GETメソッドは省略できる。
エントリポイントのClass/functionで実行されるのが決まる。
引数は、引数名がそのまま使われる。
http://example.com/rest/example/hello?to=hoge&from=adam
を受けたかったら、
<?php class Example{ function hello($to = "World", $from = "Me"){ return "Hello $to! From $from ?"; } }
とする。
POSTメソッド
クラスの各メソッドにHTTPメソッドのプレフィクスを付けるのが決まり。なので、postIndexメソッドを作るとそれが使われる。 上記の定義のまま
$ curl -X POST http://example.com/rest/example/hello
ってやると、
{ "error": { "code": 405, "message": "Method Not Allowed" }, "debug": { "source": "Routes.php:431 at route stage", "stages": { "success": [ "get" ], "failure": [ "route", "negotiate", "message" ] } } }
ってなるので、POSTに対応させるにはpostメソッドを作る。
<?php class Example{ function post($to = "World", $from = "Me"){ return "POST to $to! from $from ?"; }
これで
$ curl -X POST http://example.com/rest/example/ -H "Content-Type: application/json" -d '{"to": "ITOH", "from": "Smith"}' "POST to ITOH! from Smith ?"
と返ってくる。
XMLで返す。
$r = new Restler();
$r->setSupportedFormats('XmlFormat');
ってやると http://example.com/rest/example/hello.xml
とコールすることでXMLで返せるみたい。
みたいというのは、テスト環境でVIEWまわりを扱う"illuminate/view"がうまくインストールできてないからです。
エラーハンドリング
エラーが起こった際には、RestExceptionを投げる。
<?php throw new RestException(HTTPステータスコード, "エラーメッセージ");
エラーメッセージは省略可能。 HTTPステータスコードは500でいいんじゃないでしょうか。
デバッグモード
最初のインスタンスを作る際、コンストラクタの第一引数をtrueにするとデバッグ情報が抑えられる。
なので、実運用上では
$r = new Restler(true);
とすること。