リソース
BEAR.SundayアプリケーションはRESTfulなリソースの集合です。
サービスとしてのオブジェクト
ResourceObject
はHTTPのメソッドがPHPのメソッドにマップされたリソースのサービスのためのオブジェクト(Object-as-a-service)です。ステートレスリクエストから、リソースの状態がリソース表現として生成され、クライアントに転送されます。(Representational State Transfer)
以下は、ResourceObjectの例です。
class Index extends ResourceObject
{
public $code = 200;
public $headers = [];
public function onGet(int $a, int $b): static
{
$this->body = [
'sum' => $a + $b // $_GET['a'] + $_GET['b']
];
return $this;
}
}
class Todo extends ResourceObject
{
public function onPost(string $id, string $todo): static
{
$this->code = 201; // ステータスコード
$this->headers = [ // ヘッダー
'Location' => '/todo/new_id'
];
return $this;
}
}
PHPのリソースクラスはWebのURIと同じようなpage://self/index
などのURIを持ち、HTTPのメソッドに準じたonGet
、onPost
などのonメソッドを持ちます。onメソッドで与えられたパラメーターから自身のリソース状態code
、headers
、body
を決定し、$this
を返します。
URI
URIはPHPのクラスにマップされています。アプリケーションではクラス名の代わりにURIを使ってリソースにアクセスします。
URI | Class |
---|---|
page://self/ | Koriym\Todo\Resource\Page\Index |
page://self/index | Koriym\Todo\Resource\Page\Index |
app://self/blog/posts?id=3 | Koriym\Todo\Resource\App\Blog\Posts |
- indexは省略可能です。
スキーマ
page
は外部公開するパブリックなリソース、app
は外部からアクセスのできないプライベートなリソースです。Webやコンソールなどの外部からのリソースリクエストを受け取ったpageリソースは、appリソースをリクエストしてリソース状態を決定します。1
メソッド
リソースはHTTPのメソッドに対応した6つのメソッドでアクセスすることができます。2
GET
特定のリソースの表現をリクエストします。このメソッドはリソースの状態を変更することのない安全なメソッドです。
POST
POSTメソッドは、リクエストに含まれる表現の処理を要求します。例えば、対象のURIに新しいリソースを追加することや、既存のリソースに表現を追加することなどです。PUTと違ってリクエストには冪等性がなく、連続した複数回の実行は同じ結果になりません。
PUT
リクエストしたURIでリソースをリクエストのペイロードで置き換えます。対象のリソースが存在しない場合には作成します。 POSTと違って冪等性があります。
DELETE
特定のリソースを削除します。冪等性があります。
PATCH
リソースを部分的に変更します。冪等性は保証されません。3
OPTIONS
リソースのリクエストに必要なパラメーターとレスポンスに関する情報を取得します。GETと同じように安全です。4
メソッドの特性一覧
メソッド | 安全性 | 冪等性 | キャッシュ |
---|---|---|---|
GET | あり | あり | 可能 |
POST | なし | なし | 不可 |
PUT | なし | あり | 不可 |
PATCH | なし | あり | 不可 |
DELETE | なし | あり | 不可 |
OPTIONS | あり | あり | 不可 |
パラメーター
レスポンスメソッドの引数には、変数名に対応したリクエストの値が渡されます。
class Index extends ResourceObject
{
// $_GET['id']が$idに
public function onGet(int $id): static
{
}
// $_POST['name']が$nameに
public function onPost(string $name): static
{
}
その他のメソッドや、Cookieなどの外部変数をパラメーターに渡す方法はリソースパラメーターをご覧ください。
レンダリングと転送
ResourceObjectのリクエストメソッドではリソースの表現について関心を持ちません。インジェクトされたレンダラーがリソースの表現を生成し、レスポンダーが出力します。詳しくはレンダリングと転送をご覧ください。
クライアント
リソースクライアントを使用して他のリソースをリクエストします。以下のリクエストはapp://self/blog/posts
リソースに?id=1
というクエリーでリクエストを実行します。
use BEAR\Sunday\Inject\ResourceInject;
class Index extends ResourceObject
{
public function __construct(
private readonly ResourceInterface $resource
){}
public function onGet(): static
{
$this->body = [
'posts' => $this->resource->get('app://self/blog/posts', ['id' => 1])
];
}
}
この他にも以下の歴史的表記があります。
// PHP 5.x and up
$posts = $this->resource->get->uri('app://self/posts')->withQuery(['id' => 1])->eager->request();
// PHP 7.x and up
$posts = $this->resource->get->uri('app://self/posts')(['id' => 1]);
// getは省略可
$posts = $this->resource->uri('app://self/posts')(['id' => 1]);
遅延評価
これまでの例はリクエストをすぐに行うeager
リクエストですが、リクエスト結果ではなくリクエストを生成し、実行を遅延することもできます。
$request = $this->resource->get('app://self/posts'); // callable
$posts = $request(['id' => 1]);
このリクエストをテンプレートやリソースに埋め込むと、遅延評価されます。つまり評価されない時はリクエストは行われず、実行コストがかかりません。
$this->body = [
'lazy' => $this->resource->get('app://self/posts')->withQuery(['id' => 3])->request();
];
キャッシュ
通常のTTLキャッシュと共に、RESTのクライアントキャッシュや、CDNを含めた高度な部分キャッシュ(ドーナッツキャッシュ)をサポートします。詳しくはキャッシュをご覧ください。また、従来の@Cacheable
アノテーションに関しては以前のリソース(v1)ドキュメントをご覧ください。
リンク
重要なREST制約の1つにリソースのリンクがあります。ResourceObjectは内部リンク、外部リンクの双方をサポートします。詳しくはリソースリンクをご覧ください。
BEAR.Resource
BEAR.Sundayのリソースオブジェクトの機能は独立したパッケージで単体使用もできます。BEAR.ResourceREADMEもご覧ください。