FuelPHPのThemeを使ってスマホとPCでテンプレートを切り替える~Smarty編~

自分が運営しているサイトスマートフォン対応しようと思って戦った時のメモ。

環境

なぜ戦うことになったのか

Themeを使ってスマホとPCでテンプレートを切り替える方法についてはこのブログを参考にした。

Smartyを使うにあたってcoreのコード(fuel/core/classes/theme.php)を読むと、まずTheme#set_templateは

public function set_template($template)
{
    // make sure the template is a View
    if (is_string($template))
    {
        $this->template = $this->view($template);
    }
    else
    {
        $this->template = $template;
    }

    // return the template view for chaining
    return $this->template;
}

引数($template)が文字列でなければそのままセットする、という実装になっているのでView_Smartyのオブジェクトをそのまま投げてしまえば使える。
問題はTheme#viewで、

public function view($view, $data = array(), $auto_filter = null)
{
    if ($this->active['path'] === null)
    {
        throw new \ThemeException('You must set an active theme.');
    }

    return \View::forge($this->find_file($view), $data, $auto_filter);
}

activeなテーマのpathを探してViewのオブジェクトを作って返す、という実装になっている。
Controllerで$this->theme->view('hoge/foo')としたときに返して欲しいのはView_Smartyのオブジェクトなのでこのままでは使えない(と思う)。
というわけで、Themeを継承したサブクラスを作ってTheme#viewをオーバーライドしてしまうことにした。

Themeクラスを継承して適当にSmartyThemeとかいうクラスを作る。

class SmartyTheme extends \Fuel\Core\Theme
{
    public function view($view, $data = array(), $auto_filter = NULL) {
        if ($this->active['path'] === null) {
            throw new \ThemeException('You must set an active theme.');
        }
        return View_Smarty::forge($this->find_file($view));
    }
}

ControllerではThemeの代わりに作ったSmartyThemeを使うようにする。

$this->theme = SmartyTheme::instance(
    'custom',
    array(
        'active'   => 'pc',
        'fallback' => 'pc',
        'paths'=> array(APPPATH.'views'),
        'view_ext' => '.tpl'
    )
);

これでControllerで$this->theme->view('hoge/foo')としたときはアクティブなテーマのパスを検索しView_Smartyオブジェクトを返すようになる。

最後に

「ここまでしてSmartyを使いたかったのか?」とか「このご時世にSmarty(笑)」というのが頭に浮かぶ人もたぶんいるだろうが、すでにSmartyで書いたテンプレートがあってとか自作関数を駆使して便利になっているのでテンプレート全部書きなおすとか考えたくない。

「こんなことしなくてももっと簡単にできるぜ!」みたいなことがあれば教えてほしい…