ページはリソースリクエストを行い、そのリソースリクエストの結果(=リソース状態)をページにsetします。そのリソースリクエストが実際に行われるタイミングやページにsetされるリソース状態の種類をリソースのセットオプションで指定することができます。
リソースをページにセットするには2つの方法があります。
- ページのset()メソッドで*リソース結果*をsetする方法
BEAR_Page::set()
- リソースリクエストのメソッドチェーンで*リソースリクエスト*をsetする方法
BEAR_Ro_Prototype::set()
ページのset()メソッドでsetする方法では、リソースリクエストの結果(リソース状態)のリソースオブジェクトまたはリソースBodyの値をページにsetします。単純で直感的な方法です。
// 値をセット
$entry = $this->_resource->read($params)->getBody();
$this->set('entry', $entry);
// リソースオブジェクトをセット
$entry = $this->_resource->read($params)->getRo();
$this->set('entry', $entry);
もう一つはリソースリクエストからのメソッドチェーンで最後にset()する方法です。「リクエストの結果」ではなく「リソースリクエストの方法」をページにセットします。実リクエストはすぐには行われません。セットオプションによって、いつ(ページのonInit()終了後か、ビューに現れたタイミングか)どのような変数(バリューorオブジェクト)をページにsetするかを指定します。リソースリクエストの遅延評価(レイジーエバリュエーション)が可能な方法です。
$this->_resource->read($params)->set('entry', 'object');
$this->_resource->read($params)->set('entry', 'lazy');
- ※read($params)の返り値は
BEAR_Ro_Prototype
型です。リソースリクエスト情報(メソッド、URI、引数)を保持しそれに基づいてリクエストを行うメソッドrequest()が用意されているリソースリクエストのオブジェクトです。
メソッドチェーンで繋げてsetする場合以下のオプションがを指定することが用意されています。 以下オプションです。
オプション | セットされるもの (Value or Ro) | Eager or Lazy | 実際にリソースリクエストが行われるタイミング |
---|---|---|---|
'value' | Value | eager | onInit()の終了後 |
'object' | Resource Object | eager | onInit()の終了後 |
'lazy' | Resource Object | lazy | viewで出現したとき(のみ) |
'shutdown' | n/a | n/a | shutdown時 |
以下はサンプルコードです。
$this->_resource->read($params1)->set('entry1', 'value');
$this->_resource->read($params2)->set('entry2', 'object');
$this->_resource->read($params3)->set('entry3', 'lazy');
$this->_resource->read($params3)->set(null, 'shutdown');
セットオプションを使ったリソースリクエストは必ずonInit()内でしないといけない*事に気をつけてください。ページへのリソースリクエスト(状態ではなく)のsetはonInit()内でのみ有効です。onAction()やonOutput()でsetされたリソースはリクエストされません。これはメソッドチェーンで(BEAR_Ro_Prototype::set()
)でsetされたリソースリクエストへのページへのセットがページ初期化ハンドラ(BEAR_Page::onInit())の終わった後に行われるわけです。
setされたリソースオブジェクトやリソースの値をページテンプレートでどのように記述するかオプション毎に説明します。
テンプレートには値がsetされています。配列ならforeachなどで展開したりして使います。
{foreach item=item from=$entry}
<li>{$item.body}</li>
{/foreach}
リソーステンプレートオプションを用いるかどうかで記述がかわります。
リソーステンプレートが適用され文字列化されてページテンプレートにアサインされているのでプレースフォルダとして指定します。
{$entry}
リソースオブジェクトはArrayObject
なので配列とおなじ操作が行えます。foreachではリソースBodyの部分がループします。
{foreach item=item from=$entry}
<li>{$item.body}</li>
{/foreach}
shutdown時にリクエストされるのでテンプレートへのアサインに意味がありません。nullをsetするか後述のrequestOnShutdown()を使いましょう。
read以外の動作などで結果をページにセットしないリクエストをメソッドチェーンで記述するときは下記のようにrequest()を使います。
//即リクエスト
$this->_resource->update($params)->request();
shutdown時のリクエストするときには下記のように記述します。
// shutdown時にリソースリクエスト実行
$this->_resource->update($params)->requestOnShutdown();
$this->_resource->update($params)->set(null, 'shutdown');
- 'value'オプションを使ったsetは単純な変数のset(push)です。レイジーロードはできません。
- 'object'オプションでアサインされるオブジェクトはArrayObjectを継承したBEAR_Roです。配列としても扱えますが(foreachでbodyの部分がループします)オブジェクトとしてメソッドを使用することもできます。またリソースリクエスト時にイテレータオプション(iterator)を指定することもできます。
イーガー(eager)ではリソースリクエストがonInit終了時に行われテンプレートにsetされます。そのリクエスト結果がもしテンプレートで使わない場合はそのリソースリクエストコストは無駄になります。例えば同一URLでUAスニッフィングを行う場合、UAによってページテンプレートはかわり、必要とするリソースも変わります。リソースリクエストはその違いを考慮してUAに応じて行う必要があります。
レイジー (lazy)ではテンプレートにsetした変数が出現するまで実リソースリクエストは実行されません。UAスニッフィングの例でいうとそのページで最大限使うリソース(多くの場合PC用が基本)をレイジーセットしておいてUAページテンプレートでセットされたリソースに応じて実リクエストが行うようににします。
イーガーはonInit終了時にすべてのリソースリクエストが確定しているためinitキャッシュされますがレイジーでは確定されてないため、initキャッシュはされません。一方、もしかしたらビューテンプレートで出現しないかもしれないリソースはレイジーでsetしておくとリソースリクエストコストが無駄になりません。
以下の例では$show_ad
(広告表示)がtrueなら、「広告コンテンツ」リソースが表示され「広告表示回数リソース」がupdateされます。他のUAのテンプレートは広告がないとしても、ページ内でのリソースに対するリクエストやセットに変更はありません。表示してない「広告のカウンター」リソースをアップデートすることはありません。$show_ad
がfalseの場合も同様です。
ページ
$this->_resource->read(array('uri'=>'Ad'))->set('ad_contents', 'lazy');
$this->_resource->update(array('uri'=>'Ad/Counter'))->set('ad_counter', 'lazy');
$this->set('show_ad', true); //広告表示
PCテンプレート
{if $show_ad}
{$ad_contents}
{$ad_counter}
{/if}
携帯テンプレート
// $adはない
一般にはコンテンツプッシュとコンテンツプルと表現されます。またフレームワークを分類するのにプッシュベース、プル ベース*1とタイプわけされることもあります。※Drupalはプルと分類されています。主要PHPフレームワークの多くはプッシュベース*2です。
BEARでは'lazy'のセットオプションでビューテンプレートからリソースリクエストが行われますが、ページでのセットを全くすることなしにsmartyの{resource}プラグインを使ってPageでのリソースsetなしにリソースPullすることもできます。
リソースセットがページでないのでページで表示するリソースに変更があっても修正が用意です。例えばECサイトの商品ページをイメージしてください。ページからセットするのは商品IDだけです。そのIDに基づいて、「商品リソース」のほかに「この商品を買った人はこれも買ってますリソース」や「これがおすすめですリソース」が同じページにあります。ソーシャライズ機能を付加しようと「商品レビューリソース」を付加するときに、Pullなのでページクラスの変更がありません。またページテンプレートもプレースフォルダの追加だけなので、機能追加による影響が最小限に留めることができコラボ作業もしやすく、すぐにそのリソースを外すことができるのでメンテナンス性も向上するでしょう。(initキャッシュが効かない事には注意しましょう)
- **1http://en.wikipedia.org/wiki/Web_application_framework#Push-based_vs._Pull-based ***2http://en.wikipedia.org/wiki/Comparison_of_web_application_frameworks#PHP_2
- リソースデバックを使うと以下の様にテンプレート付リソースオブジェクトがリソースデバック表示されます
- 破線がリソーステンプレートエリアを表わし、Valueクエリー付URIとリソーステンプレートが表示されます。
- リソーステンプレートはクリックするとオンラインで編集できます。
- app.ymlでBEAR_Roにshow_box: trueをセットするとデバック時は常時表示されます。それ以外の場合はデバックモードで
?_resource
クエリーを付加すると表示されます。