はじめに
FuelPHP
にはTemplate
とREST
、そしてその両方の特性を併せ持つHybrid
というベースコントローラーがありますが、その中でHybrid
を継承元とし色々と参考にさせて頂きつつ拡張してみたので紹介です。
前提
準備
- FuelPHPをインストールしましょう
実装するにあたり決めた自分ルール
Hybrid
はREST
の機能も持っているので、HTTPメソッドに応じてコントローラのメソッドを限定する事が出来ます。
また、Ajaxによる通信が主になりそうだったので、下記の自分ルールを決めて場合分けしました。
-
Ajaxリクエストの場合→HTTPメソッドに対応したコントローラメソッドに投げる
-
action_〇〇
の場合はviewファイルの中身(<body>
とかは含まない)を返却 - その他の場合はjsonオブジェクトを返却
-
-
Ajaxリクエストでない場合→対応するviewファイル(
<body>
とかも含む)を返却 -
何なら
js
やcss
はviewオブジェクトを返却する場合はコントローラ名及びアクション名に対応するファイルがあれば勝手に読み込まれる様にしたい...!!
やってみる
①
自分ルール1と2の事を考えてまずは./fuel/app/views/
配下に以下の2ファイルを作っておきます。
template.php
<!DOCTYPE html>
<html lang="ja">
<head><!-- 省略 --></head>
<body>
<?php echo $content; ?>
</body>
</html>
contents.php
<?php echo $content; ?>
②
Hybrid
には元々そのリクエストがRESTFulか否かを判断するis_restful()
というメソッドがありますが、メソッド内ではAjaxリクエストか否かを判断しています。
Hybrid
のbefore()
でコレに引っかからないと、このタイミングでview関連の処理が出来ません。
自分ルール1でajax
リクエストでもviewファイルを返却したかったので、以下の様にしました。
before
public function is_restful()
{
return \Input::is_ajax();
}
after
public function is_restful()
{
// Ajaxリクエスト 且つ "HTTPメソッド_アクション名"というメソッドがリクエスト先のコントローラにあるか
return \Input::is_ajax() && method_exists(Request::main()->controller, mb_strtolower(\Input::method()) . '_' . Request::active()->action);
}
これはrouter()
でも同じ様な記述がありますが、
RESTFulに対応したメソッドがあるか否かまでチェックを入れる様にしました。
③
この処理を入れた事でbefore()
の処理をAjaxリクエストじゃなくても通ってしまうケースがありますので、以下の様に補填しました。
before
public function before()
{
if (!$this->is_restful()) {
if (!empty($this->template) and is_string($this->template)) {
$this->template = \View::forge($this->template);
}
}
return parent::before();
}
after
public function before()
{
if (!$this->is_restful()) {
if (!empty($this->template) && is_string($this->template)) {
// Ajaxリクエストなら`contents.php`を読む
if (Input::is_ajax() === TRUE) {
$this->template = View::forge('contents');
// Ajaxリクエストでなければ`template.php`を読む
} else {
$this->template = View::forge($this->template);
}
// `./fuel/app/views/`配下に"コントローラ名/アクション名.php"のファイルがあれば、`template.php`の`$content`へ
if (File::exists(APPPATH . 'views/' . strtolower(ltrim(mb_strstr(Request::main()->controller, '_'), '_')) . '/' . Request::active()->action . '.php') === TRUE) {
$this->template->content = View::forge(strtolower(ltrim(mb_strstr(Request::main()->controller, '_'), '_')) . '/' . Request::active()->action);
}
}
}
return parent::before();
}
これでaction_〇〇
はAjaxリクエストでcontents.php
を返してくれる様になりました。
Ajaxリクエストで無ければtemplate.php
がそのまま返却されます。
元々のREST
の機能はget_〇〇
やpost_〇〇
とキッチリ各コントローラでメソッドを定義しておけば特に影響は無いかと思います。
④
最後に自分ルール3について、これについては
【FuelPHP】コントローラーやアクション毎に自動でcss、jsを読み込む
を参考にさせて頂き、
contents.php
とtemplate.php
の両方にAsset::render()
を記述しておきます。
⑤
最後にコントローラ側のメソッドについてですが、最終的に以下の様な感じになりました。
/**
* viewファイルを返却する処理
*/
public function action_index() {
// viewファイルへ値を渡す
$this->template->content->foo = "bar";
}
/**
* データを取得する処理
*/
public function get_record() {
// データを取得して返却
return $this->response(/* 返却するデータ */);
}
/**
* データを追加する処理
*/
public function post_record() {
// データを追加してその結果を返却
return $this->response(/* 成功 or 失敗 とか */);
}
/* ...etc */
最後に
要件次第な所もありますが、最初にルールを決めて
これらのロジックを組んでたお陰で後々楽出来たかなと思います。
Ajaxリクエストでなければ通常の画面遷移でviewファイルも返ってくるし、
Ajaxリクエストでviewを書き換えたりする必要がある時でも
特に意識しなくて良くなったのでバンザーイ
ただ、もっとスマートなやり方がありそうな気もします
が、何かのご参考になれば幸いです...