fuelphpのCRUDクラス(継承用)をつくってみた

fuelphpのCRUDテンプレート デフォルトで生成されるCRUDが気に入らなかったので、自分で作ってみた。 自動生成の不満点は

  1. クラスが継承じゃないので全体を変えたいときに不便
  2. なぜかViewの方ではテンプレートを組み込む形でやっているので、好きなテンプレートエンジンへの移行がしにくいこと
  3. 確認画面がない
  4. createとeditが別々にある
  5. indexでページャーが居ない
  6. モデルにプロパティをひとつ追加した時の変更が大変

というわけでつくりました。 controller/crud.php

1
<?php class Controller_Crud extends Controller { protected $_modelClassName = NULL; protected $_inputProperties = array(); protected $_baseUri = ""; protected $_assignParams = array(); protected $_perPage = 20; /** * * @param Request $request * @param Response $response */ public function __construct(Request $request, Response $response) { parent::__construct($request, $response); $this->_init(); } /** * 初期化。 * ここをオーバーライドして設定する * */ protected function _init(){ $modelClassName = ""; $this->_confirm = true; $this->_modelClassName = $modelClassName; $this->_inputProperties = $modelClassName::properties(); $this->_baseUri = ""; $this->_assignParams = array(); $this->_perPage = 20; } /** * 一覧表示画面 * hasNext/hasPrevがあればそれぞれ次のページがある * * @param int $page * @return FuelCoreResponse */ public function action_index($page = 1) { $modelClassName = $this->_modelClassName; $query = $modelClassName::query(); $count = $query->count(); $query->limit($this->_perPage) ->offset(($page - 1) * $this->_perPage); $models = $query->get(); $smarty = ParserView_Smarty::forge($this->_baseUri . '/index.tpl') ->set('models', $models) ->set('hasNext', (bool) ($this->_perPage * $page < $count)) ->set('hasPrev', (bool) ($page > 1)) ->set('page', $page); return FuelCoreResponse::forge($smarty); } /** * データの編集 or 新規作成 * $id = null で新規作成 * ?bakc=1をつければエラーでもとってきたと判断し、セッションから情報を持ってくる * * @param int $id * @return FuelCoreResponse */ public function action_edit($id = null) { $errors = ''; $model = $this->_getModel($id); if (FuelCoreInput::get('back')) { $errors = FuelCoreSession::get_flash('errors'); $params = FuelCoreSession::get_flash('params'); $this->_setInputParamsToModel($model,$params); } $smarty = ParserView_Smarty::forge($this->_baseUri . '/edit.tpl') ->set('model', $model) ->set('errors', $errors); $this->_assignToSmarty($smarty); return FuelCoreResponse::forge($smarty); } /** * 確認画面 * $id = null で新規作成 * エラーがあればedit?back=1へリダイレクトする * * @param type $id * @return FuelCoreResponse */ public function action_confirm($id = null) { if (Input::method() != 'POST') { FuelCoreSession::set_flash('params', FuelCoreInput::post()); return FuelCoreResponse::redirect($this->_baseUri .'/edit/' . $id . "?back=1"); } $model = $this->_getModel($id); $val = $this->_getValidate($id); if (!$val->run()) { FuelCoreSession::set_flash('errors', $val->show_errors()); FuelCoreSession::set_flash('params', FuelCoreInput::post()); return FuelCoreResponse::redirect($this->_baseUri . '/edit/' . $id . "?back=1"); } $this->_setInputParamsToModel($model, FuelCoreInput::post()); FuelCoreSession::set('params', FuelCoreInput::post()); $smarty = ParserView_Smarty::forge($this->_baseUri . '/confirm.tpl') ->set('model', $model) ->set('inputProperties', $this->_inputProperties); $this->_assignToSmarty($smarty); return FuelCoreResponse::forge($smarty); } /** * 保存画面 * エラーがあればedit?back=1にリダイレクトする * 保存に成功すればindexにリダイレクトする * * @param int $id * @return FuelCoreResponse */ public function action_save($id = null) { if (Input::method() != 'POST' || Input::get('back')) { FuelCoreSession::set_flash('params', FuelCoreInput::post()); return FuelCoreResponse::redirect($this->_baseUri . '/edit/' . $id . "?back=1"); } $model = $this->_getModel($id); $val = $this->_getValidate($id); if (!$val->run()) { Session::set_flash('errors', $val->show_errors()); FuelCoreSession::set_flash('params', FuelCoreInput::post()); return FuelCoreResponse::redirect($this->_baseUri . '/edit/' . $id . "?back=1"); } $this->_setInputParamsToModel($model, FuelCoreInput::post()); if ($model and $model->save()) { Response::redirect($this->_baseUri); } else { Session::set_flash('errors', '保存できませんでした'); FuelCoreSession::set_flash('params', FuelCoreInput::post()); return FuelCoreResponse::redirect($this->_baseUri . '/edit/' . $id . "?back=1"); } return FuelCoreResponse::redirect($this->_baseUri); } /** * 削除画面 * 削除してindexへリダイレクトする * * @param int $id */ public function action_delete($id = null) { $model = $this->_getModel($id); $model->delete(); Response::redirect($this->_baseUri); } /** * スマーティーにクラス全体のデータをアサインする。 * @param ParserView_Smarty $smarty */ private function _assignToSmarty(ParserView_Smarty $smarty){ foreach ($this->_assignParams as $key => $value) { $smarty->set($key, $value); } } /** * モデルを返す。 * * @param int $id * @return OrmModel */ private function _getModel($id = NULL){ $modelClassName = $this->_modelClassName; if ($id == null) { return $modelClassName::forge(); } return $modelClassName::find($id); } /** * バリデーションを返す * @param int $id * @return FuelCoreValidation */ private function _getValidate($id = NULL){ $modelClassName = $this->_modelClassName; if ($id == null) { return $modelClassName::validate('create'); } return $modelClassName::validate('edit'); } /** * 入力許可されたプロパティのみモデルにセットする * * @param OrmModel $model * @param array $params */ private function _setInputParamsToModel($model, $params) { foreach ($this->_inputProperties as $key) { if (isset($params[$key])) { $model->set($key, $params[$key]); } } } }

自動生成のものとは画面遷移の流れがちょっと違います。 自動生成のものだと、editでバリデートまでして、その後遷移する形ですが、 自分の作ったのではconfirmでバリデートし、エラーがあればeditに戻る形をとりました。 これは、formでactionに自分のアドレスを書くのに違和感があったからです。それ以外の理由はありません。 できるだけこまかくメソッドに分けたので、多分継承してカスタマイズ・・・ができるはず。