FuelPhpで本サイト変更

fuelphpの最小限と思われるドキュメントを読んだので、fuelphpを用いてこのサイト(radio-age.com)を全体的に書き換えてみる。

もともとradio-age.comはCodeIgniterで作っていたので移行は大したことはないと思われる。

databaseを弄るのは好きじゃないので(仕事では仕方ないので使うけど)、基本ファイルベースでhtmlの管理をしている。今までと同様にfileベースのアプリを作る。

ただし一部はdatabaseを利用する予定。それは作業が進んでから。

以下、作業の流れを実況風にメモする。

最初は基本の部分をfuelphpのappに直接作る。モジュール化は後からにしたい。

fileベースのアプリケーションを作る

/var/www/docs/radio-age.com/ 以下にhtml関係ファイルを入れているのでそれを処理することにしたい。

設定ファイルをYAMLで

標準でyml,ini,jsonなどが設定ファイルで使える。

core/configにはcore/config/yml.phpが class Config_Yml extends \Config_File として存在。他にjson,ini用のクラスもあり。

core/config.phpをたどれば、\Config::load('some_full_path/foo.拡張子');でphp/yml/json/iniなどのファイルが呼び出される仕掛けになっている。

html_root:  "/var/www/docs/radio-age.com" <==yamlの例
\Config::load(APPPATH.'/config/radio-age.yml','radio-age');
echo Config::get("radio-age.html_root");/*/var/www/docs/radio-age.com*/

YAML設定の仕方

app/config/radio-age.phpを作成し一行

return \Config::load(APPPATH.'/config/radio-age.yml','radio-age');

こうしてやれば配列が返るので設定ファイルに付加される。

app/config/config.phpのalways_load配列に付加

上のradio-age.phpをFuelロード時に読み込む。

'config' => array('radio-age'),

文書ルートの設定

app/config/file.phpで行う。

'area'=>array(
'areas' => array(
        'radio-age'=>array(
            'basedir'=>\Config::get('radio-age.html_root'),
            'url'=>\Uri::base()
        ),

ファイルクラスのエリア機能を用いて、文書ルートを特定(*1)。

urlをUri::base()とすることでurlが変更になっても対応(開発サイトと公開サイトを気にしなくてもいい)。

以後、radio-ageをエリア名としてFile::instance(エリア名);でファイルを扱える。


Model

リクエストURLからファイルパスを取得してreadする。

databaseだけがモデルじゃない。

app/model/filebase.php
------
   namespace Model;
   class Filebase extends \Model {
      //処理
   }

次の順序でURLをチェック

  1. Uri::string()がemptyの場合はパスを/index.html
  2. Input:string()が/で終わってるときはパスをUri::string().'/index.html'
  3. Input:string()にドット(.)が無いときはUri::string().'/index.html'先にリダイレクト
  4. 上のいずれでも無いときはUri::string() = パス

ファイルを読み込む

ファイルハンドラを使いたかったが、なぜかfile_info()メソッドが存在しないので断念して、普通の使い方で我慢。

エラー処理上の注意

Modelからエラーのcatchをするのだから名前空間のバックスラッシュが必要だった

       $html_root = \Config::get('radio-age.html_root');
        try
        {
            $result = \File::read($html_root.DS.$this->path,'radio-age');
        }
        catch (\InvalidPathException $e) <<==ここ
        {
	  //なにか
        }

ソース例

namespace Model;
class Filebase extends \Model {
    private $path;
    private function _start(){
        $check = \Input::uri();
        $uri = \Uri::string();
        if(!$uri) { //top page
            $this->path = '/index.html';
        } elseif(preg_match('|\/$|',$check)){
            $this->path = $uri.'/index.html';
        } else {
            if(!preg_match('|\.|',$check)) {
                \Response::redirect($uri.'/'); //slashをつけてリダイレクト
            } else {
                $this->path = $uri;
            }
        }
    }
    public function get_results()
    {
        $this->_start();
        $html_root =\Config::get('radio-age.html_root');
        try
        {
            $result['info'] = \File::file_info($html_root.DS.$this->path,'radio-age');
        }
        catch (\InvalidPathException $e)
        {
            $this->path = \Config::get('radio-age.file_not_found');
            $result['info'] = \File::file_info($html_root.DS.$this->path,'radio-age');
        }
        catch (\OutsideAreaException $e)
        {
            $this->path = \Config::get('radio-age.file_not_found');
            $result['info'] = \File::file_info($html_root.DS.$this->path,'radio-age');
        }

        $realpath = $result['info']['realpath'];
        $result['content'] = \File::read($realpath,'radio-age');
        return $result;
    }
}
なんたらかんたら

viewmodel

radio-age.comのページ作成はHatenaSyntaxの省略記法に依存しているので、それを処理するためにviewmodelというのを作る。

CIにはなかった機能。

HatenaSyntax以外にも独自の省略タグ(たとえばAmazonのECSのデータをISBN番号を記述して取得とか)も使っているので結構メンドウな処理。

CIでは独自ライブラリクラスで処理していた。この概念(HTMLデータの前処理的加工)があったほうがありがたい。

app/classes/view/にhtmlparse.phpというモデル作成。

このデータはビューのapp/views/htmlparse.phpに渡される。

View

ビュー

app/views/htmlparse.phpはXML、htmlのheadなどを記述上で最終加工。

Controller

コアのコントローラを拡張

app/classes/mycontroller.phpに入れる。

モデルから得られたデータをVIewModelで加工・表示するメソッドのみを作成。

class MyController extends Controller
{
    public function parse_view($rtn)
    {
        if($rtn['html']==FALSE) {
            return View::forge('thru',$rtn['info']);//html拡張子以外はそのままpassthru(views/thru.php)
        } else {
            $view = ViewModel::forge('Htmlparse','view',false);
            $view->parse($rtn);
            return Response::forge($view->render());
        }
    }
    public function action_404()
    {
        return Response::forge(ViewModel::forge('welcome/404'), 404);
    }
}

welcome.phpのコントローラ

モデルを動作させ、その返り値をViewModelに入れるだけ。

class Controller_Welcome extends MyController
{
public function action_index()
{
        $mf = new \Model\Filebase;
        return $this->parse_view($mf->get_results());
}

おしまい

http://radio-age.com/sitetool/index.htmlのようにfacebook認証でアクセスするディレクトリ、ファイルに制限をかける場合があるので、それに関するfacebookコントローラ、facebookモデルも作って、未認証の場合/facebook/にリダイレクト(ログインや警告メッセージ)させるようにした。

ここらへんはCIよりも断然作りやすい。

移行にかかった時間

勉強をかねて、最初、コードを一切書かず、元コードも一切読まず、ドキュメントだけをひたすら読むということをしてみた。これに数時間。

コードを書き始めてから、この文を書くまでに更に10時間ぐらい。

二日ぐらい休みの日をまるまるつぶした感覚。

感想

CIより使いやすい。ただしバグやレファレンス(文書)記述と実装があわないところが散見。

注目株だが、今のところ不安定っぽいので、モジュール化やdatabase実装は見送った。

というわけでYIIでやろう

Yiiを使う

*1: fuelのDOCROOTは使わない。

this file --> last modified:2012-03-31 13:57:48