リダイレクトビューやら
どうなったか,ということですが,
そうですね,私の場合はもはやViewClassそのものをかなり拡張させているので,Ethna的にはできないことが出来るようになっていますが(何w),それは今後色々と本体のほうにもコミットできる部分をしていくつもりです.
その上で,一応現状の私のコードをば.deadlinetimer.com が現在最新のEthnaを使ったコードになってますので,APPIDが Deadline になってますが,その辺は適時読み替えてください.
Controller を拡張して,ActionClass から ViewClass に引数を渡せるようにする
どういうことかというと,まず,コントローラの trriger_WWW に細工をしています.
<?php //中略 class Deadline_Controller extends Ethna_Controller { // 中略 /** override */ /** * フレームワークの処理を実行する(WWW) * * 引数$default_action_nameに配列が指定された場合、その配列で指定された * アクション以外は受け付けない(指定されていないアクションが指定された * 場合、配列の先頭で指定されたアクションが実行される) * * @access private * @param mixed $default_action_name 指定のアクション名 * @param mixed $fallback_action_name アクション名が決定できなかった場合に実行されるアクション名 * @return mixed 0:正常終了 Ethna_Error:エラー */ function _trigger_WWW($default_action_name = "", $fallback_action_name = "") { // アクション名の取得 $action_name = $this->_getActionName($default_action_name, $fallback_action_name); // マネージャ実行チェック $this->_ethnaManagerEnabledCheck($action_name); // アクション定義の取得 $action_obj =& $this->_getAction($action_name); if (is_null($action_obj)) { if ($fallback_action_name != "") { $this->logger->log(LOG_DEBUG, 'undefined action [%s] -> try fallback action [%s]', $action_name, $fallback_action_name); $action_obj =& $this->_getAction($fallback_action_name); } if (is_null($action_obj)) { return Ethna::raiseError("undefined action [%s]", E_APP_UNDEFINED_ACTION, $action_name); } else { $action_name = $fallback_action_name; } } // アクション実行前フィルタ for ($i = 0; $i < count($this->filter_chain); $i++) { $r = $this->filter_chain[$i]->preActionFilter($action_name); if ($r != null) { $this->logger->log(LOG_DEBUG, 'action [%s] -> [%s] by %s', $action_name, $r, get_class($this->filter_chain[$i])); $action_name = $r; } } $this->action_name = $action_name; // オブジェクト生成 $backend =& $this->getBackend(); $form_name = $this->getActionFormName($action_name); $this->action_form =& new $form_name($this); $this->action_form->setFormVars(); $backend->setActionForm($this->action_form); // アクションに必要とされる全てのオブジェクトが // 初期化されたあと、言語切り替えフックを呼ぶ $session =& $this->getSession(); $session->restore(); $this->_setLanguage($this->locale, $this->system_encoding, $this->client_encoding); // バックエンド処理実行 $forward_name = $backend->perform($action_name); // アクション実行後フィルタ for ($i = count($this->filter_chain) - 1; $i >= 0; $i--) { $r = $this->filter_chain[$i]->postActionFilter($action_name, $forward_name); if ($r != null) { $this->logger->log(LOG_DEBUG, 'forward [%s] -> [%s] by %s', $forward_name, $r, get_class($this->filter_chain[$i])); $forward_name = $r; } } // コントローラで遷移先を決定する(オプション) $forward_name_params = $this->_sortForward($action_name, $forward_name); // override による 変更箇所はココだよー! $preforward_params = array(); if (is_array($forward_name_params)) { $forward_name = array_shift($forward_name_params); $preforward_params = $forward_name_params; } else { $forward_name = $forward_name_params; } if ($forward_name != null) { $view_class_name = $this->getViewClassName($forward_name); $this->view =& new $view_class_name($backend, $forward_name, $this->_getForwardPath($forward_name)); //$this->view->preforward(); // ここだよー $preforward_return = call_user_func_array(array($this->view, 'preforward'), $preforward_params); $this->view->forward(); } return 0; } }
ViewClass の基底を拡張する
これも色々いじってるんですが,とりあえずもうちょいまとまったらちゃんとコード出すつもりでしたが,とりあえず現状どうなってるかだけ.
色々やってますが,簡単にいえば,
- header吐けるメソッドを用意した
- レイアウトテンプレートにした
- そんくらいだっけ・・・・?
あれ?なんだこのコード flush まわりが中途半端だぞ!?とりあえず今は気にしない.
ちなみに,以下のViewClassを,Deadline_ViewClassが継承しています.
<?php /** * Ether_ViewClass.php * * @description ViewClass Ether Expansion: expand methods, utilities. * @author Sotaro KARASAWA * @package Ether : Ethna Expansion * @date 2008/09/23 * @version $Id: app.viewclass.php 600 2008-06-30 23:12:42Z mumumu-org $ */ // Ether_ViewClass /** * View class. * * @author Sotaro KARASAWA * @package Ether : Ethna Expansion * @access public */ class Ether_ViewClass extends Ethna_ViewClass { /** * @purotected string Layout template filename */ protected $_layoutFile = 'layout.tpl'; /** * @public boolean flag of use layout template */ public $hasLayout = true; public $hasDefaultHeader = true; public $defaultHeader = array( "Pragma" => "no-cache", "Cache-Control" => "no-cache, no-store, must-revalidate", ); /** * Constructor of ViewClas * to over ride * * @access public * @param object Ethna_Backend $backend backendオブジェクト * @param string $forward_name ビューに関連付けられている遷移名 * @param string $forward_path ビューに関連付けられているテンプレートファイル名 */ public function Ether_ViewClass(&$backend, $forward_name, $forward_path) { parent::Ethna_ViewClass($backend, $forward_name, $forward_path); $this->db =& Ether_DB::getInstance($backend); } /** * set common default value. * * @access protected * @param object Deadline_Renderer Renderer object. */ function _setDefault(&$renderer) { // get config setting- $isDebug = $this->backend->getConfig()->get('debug'); $isTplDebug = $this->backend->getConfig()->get('debug_tpl'); $smarty =& $renderer->engine; // あ,ここもデフォルトから変えてるな $smarty->left_delimiter = '{{'; $smarty->right_delimiter = '}}'; // for debug $smarty->force_compile = $isDebug; $config =& $this->backend->getConfig(); } /** * Override parent method to set Layout Template * * @access public */ public function forward() { $this->_setLanguage(); $renderer =& $this->_getRenderer(); $this->_setDefault($renderer); if ($this->hasDefaultHeader) { $this->defaultHeader['Content-Type'] = 'text/html; charset=' . $this->backend->getController()->getClientEncoding(); $this->header($this->defaultHeader); } // using layout.tpl flag if ($this->hasLayout) { // check : layout file existance $layout = $this->getLayout(); if ($this->isTemplateExists($layout)) { $content = $renderer->perform($this->forward_path, true); if (Ethna::isError($content)) { if ($content->getCode() == E_GENERAL) { $error = 404; } else { $error = 500; } $this->error($error); $content = $renderer->perform($this->forward_path, true); } $renderer->assign('content', $content); $renderer->display($layout, serialize($_SERVER['REQUEST_URI'])); } else { return Ethna::raiseWarning('file "'.$layout.'" not found'); } } else { $renderer->perform($this->forward_path); } } /** * sending header * * @param mixed array send header : heade => value * int HTTP status code * string Header string */ public function header ($status) { if (is_array($status)) { foreach ($status as $key => $status) { header ($key . ": " . $status); } } else if (is_int($status)) { $codes = array( 100 => "Continue", 101 => "Switching Protocols", 200 => "OK", 201 => "Created", 202 => "Accepted", 203 => "Non-Authoritative Information", 204 => "No Content", 205 => "Reset Content", 206 => "Partial Content", 300 => "Multiple Choices", 301 => "Moved Permanently", 302 => "Found", 303 => "See Other", 304 => "Not Modified", 305 => "Use Proxy", 307 => "Temporary Redirect", 400 => "Bad Request", 401 => "Unauthorized", 402 => "Payment Required", 403 => "Forbidden", 404 => "Not Found", 405 => "Method Not Allowed", 406 => "Not Acceptable", 407 => "Proxy Authentication Required", 408 => "Request Time-out", 409 => "Conflict", 410 => "Gone", 411 => "Length Required", 412 => "Precondition Failed", 413 => "Request Entity Too Large", 414 => "Request-URI Too Large", 415 => "Unsupported Media Type", 416 => "Requested range not satisfiable", 417 => "Expectation Failed", 500 => "Internal Server Error", 501 => "Not Implemented", 502 => "Bad Gateway", 503 => "Service Unavailable", 504 => "Gateway Time-out" ); if (array_key_exists($status, $codes)) { header("HTTP/1.1: {$status} {$codes[$status]}"); //vd("HTTP/1.1: {$status} {$codes[$status]}"); } } else { // check valid header if (preg_match("/^.+\:\s.+$/", $status)) { header($status); } } } public function redirect ($url) { $this->hasDefaultHeader = false; $this->hasLayout = false; $this->header(302); $this->header(array('Location' => $url)); } public function flush ($url, $message = "", $wait = 3) { $flush = compact($url, $message, $wait); $this->af->setApp('flush', $flush); } /** * set layout */ public function setLayout ($filename) { // check layout file existance if ($this->isTemplateExists($filename)) { $this->_layoutFile = $filename; return true; } else { return Ethna::raiseWarning('file "'.$filename.'" not found'); } } /** * get layout */ public function getLayout () { return $this->_layoutFile; } /** * check template existance * * @param string $filename template file name * @access public * @return boolean */ public function isTemplateExists($filename) { $renderer = $this->_getRenderer(); if ($renderer->templateExists($filename)) { return true; } else { return false; } } /** * Error */ function error($code) { $this->hasDefaultHeader = false; $this->header($code); // template 以下に error404.tpl とかがあれば, preforward で $this->error(404); とかすればいい $this->forward_path = "error{$code}.tpl"; } }
ActionClass で引数を渡して redirect viewに return
Redirect ViewClass は以下の通り.
<?php class Deadline_View_Redirect extends Deadline_ViewClass { /** * preprocess before forwarding. * * @access public */ function preforward($url = null) { if (is_null($url)) { $this->redirect($this->config->get('url')); } else { if ($this->isAbsoluteUrl($url)) { $this->redirect($url); } else { if (substr($this->config->get('url'), -1) === '/') { $base = $this->config->get('url'); } else { $base = $this->config->get('url') . '/'; } if (substr($url, 0) === '/') { $suff = substr($url, 1); } else { $suff = $url; } $this->redirect($base . $suff); } } // TODO: ここでexitしてるとテストがうごかないから forward 側でうんちゃらする exit; } function isAbsoluteUrl($url) { if (preg_match("@^(https?|ftp)://.+@", $url)) { return true; } else { return false; } } } ?>
例えば,以下のがDeadlinetimerでタイマーを登録するActionClass.DBも結構手をいれてますのでその辺は適当にw
<?php /** * register action implementation. * * @author Sotaro KARASAWA <sotaro.k@gmail.com> * @access public * @package Deadline */ class Deadline_Action_Register extends Deadline_ActionClass { /** * preprocess of register Action. * * @access public * @return string forward name(null: success. * false: in case you want to exit.) */ function prepare() { if ($this->af->validate() > 0) { return 'index'; } return null; } /** * register action implementation. * * @access public * @return string forward name. */ function perform() { $data = $this->af->getArray(); $this->db->Timer->setArray($data); $id = $this->db->Timer->save(); if (Ethna::isError($id)) { return $this->error($id); } else { return array('redirect', "timer/$id",); } } }
そんなかんじで,
return array('redirect', "/hoge");
とか
return array('redirect', "http://deadlinetimer.com");
とか,当然
return 'redirect';
とかだとトップに飛んだりなど.
まとまってなくてすみませんw
超中途半端なまま放置した
にもブクマくださっているみたいなので,現状私がどうしているかだけ書いておこうと思ってw
参考になれば幸いです.