active_record_helperでも同様な現象があったので、「こちら」の記事は参考にしてください。
◎変更箇所
lib\AkActionView\helpers\form_helper.php(338L近辺)
◎変更前
$options['value'] = !empty($options['value']) ? $options['value'] : $this->value_before_type_cast();
◎変更後
$options['value'] = !empty($options['value']) || is_numeric(@$options['value']) ? $options['value'] : $this->value_before_type_cast();
◎変更箇所
lib\AkActionView\helpers\form_helper.php(338L近辺)
◎変更前
$options['value'] = !empty($options['value']) ? $options['value'] : $this->value_before_type_cast();
◎変更後
$options['value'] = !empty($options['value']) || is_numeric(@$options['value']) ? $options['value'] : $this->value_before_type_cast();
form タグに enctype="multipart/form-data" を追加するには、以下のように start_form_tag() 関数の第2パラメータとして「array('multipart'=>true)」を記述する。
= $form_tag_helper->start_form_tag(array('action'=>'add'), array('multipart'=>true)) ?>
これでファイルのアップロードが可能となる。
= $form_tag_helper->start_form_tag(array('action'=>'add'), array('multipart'=>true)) ?>
これでファイルのアップロードが可能となる。
active_record_helper でファイルタイプの入力ボックスを表示するには、ドキュメントを見た感じでは以下のようにビューに記述すれば良いように思えたが、
$active_record_helper->input('image', 'filename', array('type'=>'file');
単なるテキスト入力になってしまった。
そこでソースを追ってみたのだが、結局以下のように対処した。
・lib/AkActionView/helpers/active_record_helper.php(188L辺り)
・変更前
$field_type = strstr($this->method_name,'password') ? 'password' : 'text';
・変更後
if(empty($options['type']))
$field_type = strstr($this->method_name,'password') ? 'password' : 'text';
else
$field_type = $options['type'];
$active_record_helper->input('image', 'filename', array('type'=>'file');
単なるテキスト入力になってしまった。
そこでソースを追ってみたのだが、結局以下のように対処した。
・lib/AkActionView/helpers/active_record_helper.php(188L辺り)
・変更前
$field_type = strstr($this->method_name,'password') ? 'password' : 'text';
・変更後
if(empty($options['type']))
$field_type = strstr($this->method_name,'password') ? 'password' : 'text';
else
$field_type = $options['type'];
「waves」というモデルを作成し、前記モデルからビューでデータを抽出するために、例えば以下のようなSintagsを記述した。
{loop waves}
・
・
{end}
しかし正常にデータを「waves」モデルから取得する事ができなかった。
コンパイルされたビューファイルを見ると、以下のように「waves」を単数化する際に「wafe」と誤変換してしまっているではないか。
if(!empty($waves))
foreach ($waves as $wafe_loop_key=>$wafe){
$wafe_loop_counter++;
$wafe_is_first = $wafe_loop_counter === 1;
$wafe_is_last = $wafe_loop_counter === $waves_available;
・
・
}
Akelosのドキュメントを見たが、対処方法がどこに書いてあるか分らなかったので、ソースを追って見る事とした。
結論から言うと対処方法については以下の通り。
・lib/Akinfector.php(169L辺り)
singularize()という関数内に $irregular というアレイ型の変数が定義されているので、この変数に「'wave' => 'waves'」のように変換したい内容を追加すれば良い。
なお pluralize()という関数もあるので、確かめてはいないが、複数化する際に使用すると思われる。この関数内にも $irregular 変数が定義されているので、同様の修正をしておいた方が良いと思われる。
{loop waves}
・
・
{end}
しかし正常にデータを「waves」モデルから取得する事ができなかった。
コンパイルされたビューファイルを見ると、以下のように「waves」を単数化する際に「wafe」と誤変換してしまっているではないか。
if(!empty($waves))
foreach ($waves as $wafe_loop_key=>$wafe){
$wafe_loop_counter++;
$wafe_is_first = $wafe_loop_counter === 1;
$wafe_is_last = $wafe_loop_counter === $waves_available;
・
・
}
Akelosのドキュメントを見たが、対処方法がどこに書いてあるか分らなかったので、ソースを追って見る事とした。
結論から言うと対処方法については以下の通り。
・lib/Akinfector.php(169L辺り)
singularize()という関数内に $irregular というアレイ型の変数が定義されているので、この変数に「'wave' => 'waves'」のように変換したい内容を追加すれば良い。
なお pluralize()という関数もあるので、確かめてはいないが、複数化する際に使用すると思われる。この関数内にも $irregular 変数が定義されているので、同様の修正をしておいた方が良いと思われる。
以前の記事で「flash」という変数について触れたが、renderAction で「flash」変数と同じ事をしたい場合には「flash_now」変数を使用すれば良い事が分った。
以下の出典はここ
-----------------------------------------------------
CommentAuthorjervis CommentTimeSep 10th 2007 edited
$this->flash['notice'] = $result['ErrMsg'];
$this->renderAction("login");
The flash content cannot display, how to send this flash's content to the Action Class, thank you :)
CommentAuthorbermi CommentTimeSep 10th 2007
Flash will be shown on the next Request, flash_now on the same Request.
renderAction() does not start a new request, it simply delegates the response to a different action
$this->flash_now['notice'] = $result['ErrMsg'];
will work in your case.
以下の出典はここ
-----------------------------------------------------
CommentAuthorjervis CommentTimeSep 10th 2007 edited
$this->flash['notice'] = $result['ErrMsg'];
$this->renderAction("login");
The flash content cannot display, how to send this flash's content to the Action Class, thank you :)
CommentAuthorbermi CommentTimeSep 10th 2007
Flash will be shown on the next Request, flash_now on the same Request.
renderAction() does not start a new request, it simply delegates the response to a different action
$this->flash_now['notice'] = $result['ErrMsg'];
will work in your case.
「この記事」を参考に携帯対応を組み込んでみた。
今回は config.php, application_controller.php を修正し、mobile_application_controller.php を追加した。
また、「.htaccess」などで「php_value session.use_trans_sid 1」を設定しておくものとする。
(1)config.php
「boot.php」をインクルードする前に以下のコードを記述する。
function is_mobile()
{
require_once 'Net/UserAgent/Mobile.php';
$userAgent = Net_UserAgent_Mobile::singleton();
return !$userAgent->isNonMobile();
}
is_mobile() ? define('AK_CHARSET', 'SJIS') : define('AK_CHARSET', 'UTF-8');
これを記述しないと、ドコモのi-modeエミュレータソフトでは文字化けが発生した。なお、これを記述しなくても、AUとSBのエミュレータソフトでは文字化けは発生しなかった。
(2)application_controller.php
ApplicationController を MobileApplicationController(独自クラス)から派生させるようにした。
・変更前:
class ApplicationController extends AkActionController
・変更後:
class ApplicationController extends MobileApplicationController
(3)mobile_application_controller.php
以下のように記述した。
require_once(AK_LIB_DIR.DS.'AkActionController.php');
class MobileApplicationController extends AkActionController
{
function __construct()
{
parent::__construct();
MobileApplicationController::_init();
}
function _init()
{
$this->beforeFilter('_mobileIn');
$this->afterFilter('_mobileOut');
}
function defaultUrlOptions($options)
{
if(strlen(SID) > 0){
unset($_COOKIE);
return array(session_name() => session_id());
}
}
function _is_mobile()
{
return is_mobile();
}
function _mobileIn()
{
if($this->_is_mobile())
mb_convert_variables('UTF-8', 'SJIS', $this->params);
}
function _mobileOut()
{
if($this->_is_mobile()){
$this->setDefaultTemplateName('mobile/' . $this->params['action']);
$this->setLayout('mobile/' . $this->layout);
}
}
function _afterRender()
{
if($this->_is_mobile()){
if(is_string($this->Response->body)){
$this->Response->body = mb_convert_encoding($this->Response->body, 'SJIS', 'UTF-8');
}
}
}
function process(&$Request, &$Response)
{
/*
* ここに最後の行($this->Response->outputResults();)を除き、
* AkActionController::process 関数の内容をコピー
*
* lib に手を入れたくなかったので、process関数毎オーバーライド
*/
$this->_afterRender();
$this->Response->outputResults();
}
}
今回は config.php, application_controller.php を修正し、mobile_application_controller.php を追加した。
また、「.htaccess」などで「php_value session.use_trans_sid 1」を設定しておくものとする。
(1)config.php
「boot.php」をインクルードする前に以下のコードを記述する。
function is_mobile()
{
require_once 'Net/UserAgent/Mobile.php';
$userAgent = Net_UserAgent_Mobile::singleton();
return !$userAgent->isNonMobile();
}
is_mobile() ? define('AK_CHARSET', 'SJIS') : define('AK_CHARSET', 'UTF-8');
これを記述しないと、ドコモのi-modeエミュレータソフトでは文字化けが発生した。なお、これを記述しなくても、AUとSBのエミュレータソフトでは文字化けは発生しなかった。
(2)application_controller.php
ApplicationController を MobileApplicationController(独自クラス)から派生させるようにした。
・変更前:
class ApplicationController extends AkActionController
・変更後:
class ApplicationController extends MobileApplicationController
(3)mobile_application_controller.php
以下のように記述した。
require_once(AK_LIB_DIR.DS.'AkActionController.php');
class MobileApplicationController extends AkActionController
{
function __construct()
{
parent::__construct();
MobileApplicationController::_init();
}
function _init()
{
$this->beforeFilter('_mobileIn');
$this->afterFilter('_mobileOut');
}
function defaultUrlOptions($options)
{
if(strlen(SID) > 0){
unset($_COOKIE);
return array(session_name() => session_id());
}
}
function _is_mobile()
{
return is_mobile();
}
function _mobileIn()
{
if($this->_is_mobile())
mb_convert_variables('UTF-8', 'SJIS', $this->params);
}
function _mobileOut()
{
if($this->_is_mobile()){
$this->setDefaultTemplateName('mobile/' . $this->params['action']);
$this->setLayout('mobile/' . $this->layout);
}
}
function _afterRender()
{
if($this->_is_mobile()){
if(is_string($this->Response->body)){
$this->Response->body = mb_convert_encoding($this->Response->body, 'SJIS', 'UTF-8');
}
}
}
function process(&$Request, &$Response)
{
/*
* ここに最後の行($this->Response->outputResults();)を除き、
* AkActionController::process 関数の内容をコピー
*
* lib に手を入れたくなかったので、process関数毎オーバーライド
*/
$this->_afterRender();
$this->Response->outputResults();
}
}
migrate のインストーラでテーブルを定義する際に、フィールド名の前にアスタリスクを付けると(config.iniに設定してある使用言語に対応した)多言語対応のフィールドを自動的に生成してくれる。
以下の英文においては「*description」が多言語対応のフィールドとして記述してある。
scaffoldで足場を生成してみたところ、ビューの記述も「active_record_helper」を使って記述しておけば、現在の言語に合わせて適切にHTMLタグの「name」属性を設定してくれるので、特別に言語を意識して記述する必要はない。
以下の出典はここ
------------------------
I would better have a courses_controller for showing/managing Bachelor and Master models. You can use single table inheritance (see inline docs at lib/AkActiveRecord.php) and create a Course model and a courses table, including a type column for storing the course type. Then Bachelor and Master should extend the model Course.
I would move static content to the website_controller and use an action for each static page.
You can create multilingual columns prefixing the column name with and asterisk like in this example:
<?php
class CourseInstaller extends AkInstaller
{
function up_1()
{
$this->createTable('courses', '
id,
type,
*description,
starts_on,
ends_on,
location
');
}
function down_1()
{
$this->dropTable('courses');
}
}
?>
If you run this migration and your application is configured to work in en,es,de,fr locales, these columns will be created automatically by the migration
en_description
es_description
de_description
fr_description
Then whenever you want to create a view for managing those fields you can use the column name straight away or this format:
<input type="text" name="course[description][es]" />
<input type="text" name="course[description][en]" />
…
And set the course details as normal using
$Model->setAttributes($this->params['course'])
Remember to include the model you'll use in the course_controller by setting
var $models = 'course,bachelor,master';
or using
Ak::import('course,bachelor,master');
at the top of your controller.
BTW, you should join #akelos at irc.freenode.net, the is already a nice CMS on the go that might suit your needs :)
以下の英文においては「*description」が多言語対応のフィールドとして記述してある。
scaffoldで足場を生成してみたところ、ビューの記述も「active_record_helper」を使って記述しておけば、現在の言語に合わせて適切にHTMLタグの「name」属性を設定してくれるので、特別に言語を意識して記述する必要はない。
以下の出典はここ
------------------------
I would better have a courses_controller for showing/managing Bachelor and Master models. You can use single table inheritance (see inline docs at lib/AkActiveRecord.php) and create a Course model and a courses table, including a type column for storing the course type. Then Bachelor and Master should extend the model Course.
I would move static content to the website_controller and use an action for each static page.
You can create multilingual columns prefixing the column name with and asterisk like in this example:
<?php
class CourseInstaller extends AkInstaller
{
function up_1()
{
$this->createTable('courses', '
id,
type,
*description,
starts_on,
ends_on,
location
');
}
function down_1()
{
$this->dropTable('courses');
}
}
?>
If you run this migration and your application is configured to work in en,es,de,fr locales, these columns will be created automatically by the migration
en_description
es_description
de_description
fr_description
Then whenever you want to create a view for managing those fields you can use the column name straight away or this format:
<input type="text" name="course[description][es]" />
<input type="text" name="course[description][en]" />
…
And set the course details as normal using
$Model->setAttributes($this->params['course'])
Remember to include the model you'll use in the course_controller by setting
var $models = 'course,bachelor,master';
or using
Ak::import('course,bachelor,master');
at the top of your controller.
BTW, you should join #akelos at irc.freenode.net, the is already a nice CMS on the go that might suit your needs :)
以下の出典はここ
---------------------------------------------------------
Akelosでケータイ
2007/08/21 |Cake→Akelos |comments(0) |trackbacks(0) |print
Akelosでの携帯対応。いつものごとく、文字コードと、セッションのURLリライトと、ビューの切替。
携帯対策。フレームワーク変わるたびに調べなきゃならん。。。
要件は、だいたい決まって3つ。
・携帯のときは、入出力をSJISで(主にKDDI対策)。
通常のPC版は、INTERNALもDBも出力もUTF8で統一。
・クッキーに対応していない場合は、URLリライト(主にDoCoMo対策)。
・携帯向けのViewは、別に用意する(ファイルはUTF8)。
3ついっぺんに解決します。
まずは、設定の追加。
■config.php
define('AK_URL_REWRITE_ENABLED',true);
define('AK_SESSION_NAME','AK_SESSION');
function is_mobile(){ //テキトー
return strpos( $_SERVER["HTTP_USER_AGENT"], "DoCoMo" );
}
is_mobile() ?
define("AK_CHARSET","SJIS")
: define("AK_CHARSET","UTF-8");
Akelos(0.7.1)の場合、携帯かどうかの判定は、かなり早い段階にやらないといけない。なぜなら、AK_CHARSETを早くdefineしたいから。この値が、レスポンスヘッダーの、Content-Typeにセットされる。
次に、アクションレンダーが終わった後にフックしてもらう独自仕様、afterRenderを作る。
■lib/AkActionController/AkWebRequest::_after
function _after(&$Controller){
:
//++最後に1行追加
if(method_exists($Controller,'afterRender')) $Controller->afterRender();
}
以上でAkelosフレームワーク側の準備は完了。
オオモトのApplicationControllerは、こんな風に定義しておく。
class ApplicationController extends AkActionController {
//クッキーレス対応。Railsと同じ。
function defaultUrlOptions($options){
if( ! $_SERVER["HTTP_COOKIE"] )
return array( session_name() => session_id() );
}
function _mobileIn(){
if( is_mobile() )
//入力パラメータを SJIS→UTF-8変換
mb_convert_variables("UTF-8", "SJIS", $this->params);
}
function _mobileOut(){
if( is_mobile() ){
//モバイル用のレイアウトとViewに切り替える。
$this->setDefaultTemplateName("mobile/".$this->params['action']);
$this->setLayout("mobile_".$this->params['controller']);
}
}
function afterRender(){
if( is_mobile() ){
//レンダリングが終わった後のコンテンツを UTF-8→SJISに変換
if( is_string($this->Response->body) ){
$this->Response->body
= mb_convert_encoding($this->Response->body,"SJIS","UTF-8");
}
}
}
}
あとは、各コントローラでフィルターをかませば、対策完了です。
class BlogController extends ApplicationController{
function __construct(){
$this->beforeFilter('_mobileIn');
$this->afterFilter('_mobileOut');
}
}
上記の方法では、
ビュー以外のモデル・コントローラーは完全に再利用します。
その上で気をつける点は、AJAXやJavaScriptに頼ったページ遷移ではなく、オーソドックスなページ遷移で作っておくこと(お金と時間がナイばあい)。
あとは、全てのURLの生成にUrlForを使うようにしておかないと、defaultUrlOptionsは利きません。
$url = array("controller"=>"blog","action"=>"index");
もしそうしていなければ、PHPならdefaultUrlOptionsの代わりに、
リーサルウエポン session.use_trans_sid=on があります。
---------------------------------------------------------
Akelosでケータイ
2007/08/21 |Cake→Akelos |comments(0) |trackbacks(0) |print
Akelosでの携帯対応。いつものごとく、文字コードと、セッションのURLリライトと、ビューの切替。
携帯対策。フレームワーク変わるたびに調べなきゃならん。。。
要件は、だいたい決まって3つ。
・携帯のときは、入出力をSJISで(主にKDDI対策)。
通常のPC版は、INTERNALもDBも出力もUTF8で統一。
・クッキーに対応していない場合は、URLリライト(主にDoCoMo対策)。
・携帯向けのViewは、別に用意する(ファイルはUTF8)。
3ついっぺんに解決します。
まずは、設定の追加。
■config.php
define('AK_URL_REWRITE_ENABLED',true);
define('AK_SESSION_NAME','AK_SESSION');
function is_mobile(){ //テキトー
return strpos( $_SERVER["HTTP_USER_AGENT"], "DoCoMo" );
}
is_mobile() ?
define("AK_CHARSET","SJIS")
: define("AK_CHARSET","UTF-8");
Akelos(0.7.1)の場合、携帯かどうかの判定は、かなり早い段階にやらないといけない。なぜなら、AK_CHARSETを早くdefineしたいから。この値が、レスポンスヘッダーの、Content-Typeにセットされる。
次に、アクションレンダーが終わった後にフックしてもらう独自仕様、afterRenderを作る。
■lib/AkActionController/AkWebRequest::_after
function _after(&$Controller){
:
//++最後に1行追加
if(method_exists($Controller,'afterRender')) $Controller->afterRender();
}
以上でAkelosフレームワーク側の準備は完了。
オオモトのApplicationControllerは、こんな風に定義しておく。
class ApplicationController extends AkActionController {
//クッキーレス対応。Railsと同じ。
function defaultUrlOptions($options){
if( ! $_SERVER["HTTP_COOKIE"] )
return array( session_name() => session_id() );
}
function _mobileIn(){
if( is_mobile() )
//入力パラメータを SJIS→UTF-8変換
mb_convert_variables("UTF-8", "SJIS", $this->params);
}
function _mobileOut(){
if( is_mobile() ){
//モバイル用のレイアウトとViewに切り替える。
$this->setDefaultTemplateName("mobile/".$this->params['action']);
$this->setLayout("mobile_".$this->params['controller']);
}
}
function afterRender(){
if( is_mobile() ){
//レンダリングが終わった後のコンテンツを UTF-8→SJISに変換
if( is_string($this->Response->body) ){
$this->Response->body
= mb_convert_encoding($this->Response->body,"SJIS","UTF-8");
}
}
}
}
あとは、各コントローラでフィルターをかませば、対策完了です。
class BlogController extends ApplicationController{
function __construct(){
$this->beforeFilter('_mobileIn');
$this->afterFilter('_mobileOut');
}
}
上記の方法では、
ビュー以外のモデル・コントローラーは完全に再利用します。
その上で気をつける点は、AJAXやJavaScriptに頼ったページ遷移ではなく、オーソドックスなページ遷移で作っておくこと(お金と時間がナイばあい)。
あとは、全てのURLの生成にUrlForを使うようにしておかないと、defaultUrlOptionsは利きません。
$url = array("controller"=>"blog","action"=>"index");
もしそうしていなければ、PHPならdefaultUrlOptionsの代わりに、
リーサルウエポン session.use_trans_sid=on があります。
AkActionView::renderPartial のプロトタイプは以下のようになっている。
void renderPartial ( $partial_path, $object, [ $local_assigns = array()])
プロトタイプに関する情報源はここ
第一パラメータの「$partial_path」は、パスを指定する事ができるが、ディレクトリセパレータは「/」を使用しなくてはいけない。
自身の動作環境はWindows+XAMPPで構築しており、「DS」などのディレクトリセパレータ用のマクロが折角定義されているのだが、前記マクロを使用するとディレクトリセパレータが「\」になってしまう。
Akelos 0.8 の renderPartial() の処理を追って見たところ、ディレクトリ名とテンプレート名を(_partialPathPieceという関数内で)分離する際に、ディレクトリセパレータが「/」である事が前提になっていた。ディレクトリセパレータが「\」ではディレクトリ名とテンプレート名を分離できずに正しいパスを指定してもエラーとなってしまった。
なお「$partial_path」は絶対パスだけでなく、相対パス指定をする事もでき、その場合の基点となるディレクトリは「app/views」である。
なぜ「$partial_path」にパスを含める必要性が生じたかというと、レイアウトファイル内で部分テンプレートを使用したかったのだが、renderPartial()は各コントローラのメソッドのため、パスを含めないと各コントローラに対応するビューディレクトリにある部分テンプレートファイルを適用しようとしてしまう。
そこで例えば「$partial_path」を「layouts/test」とした場合、「app/views/layouts」ディレクトリ内の「_test.tpl」をどのコントローラからも部分テンプレートファイルとして適用できるようになる。
void renderPartial ( $partial_path, $object, [ $local_assigns = array()])
プロトタイプに関する情報源はここ
第一パラメータの「$partial_path」は、パスを指定する事ができるが、ディレクトリセパレータは「/」を使用しなくてはいけない。
自身の動作環境はWindows+XAMPPで構築しており、「DS」などのディレクトリセパレータ用のマクロが折角定義されているのだが、前記マクロを使用するとディレクトリセパレータが「\」になってしまう。
Akelos 0.8 の renderPartial() の処理を追って見たところ、ディレクトリ名とテンプレート名を(_partialPathPieceという関数内で)分離する際に、ディレクトリセパレータが「/」である事が前提になっていた。ディレクトリセパレータが「\」ではディレクトリ名とテンプレート名を分離できずに正しいパスを指定してもエラーとなってしまった。
なお「$partial_path」は絶対パスだけでなく、相対パス指定をする事もでき、その場合の基点となるディレクトリは「app/views」である。
なぜ「$partial_path」にパスを含める必要性が生じたかというと、レイアウトファイル内で部分テンプレートを使用したかったのだが、renderPartial()は各コントローラのメソッドのため、パスを含めないと各コントローラに対応するビューディレクトリにある部分テンプレートファイルを適用しようとしてしまう。
そこで例えば「$partial_path」を「layouts/test」とした場合、「app/views/layouts」ディレクトリ内の「_test.tpl」をどのコントローラからも部分テンプレートファイルとして適用できるようになる。
レイアウトを変更する方法については、以下の2通りの方法がある。
1.コントラーラ全体に適用
コントローラ全体に適用する場合には、コントローラのメンバー変数として「$layout」を定義して、前記メンバー変数にレイアウトを指定する。例えばレイアウトを「default.tpl」にしたい場合には、「default」と前記メンバー変数に設定すれば良い。
「default.tpl」と設定するとレイアウトを正しく適用できなくので注意する事。(10分位悩みました)
2.アクション毎に適用
render()関数のパラメータとして、キーを「layout」、前記キーの値に例えば「spectacular」と設定した連想配列を設定すると、render()関数で実行するアクションで「spectacular」レイアウトを適用する事ができる。
以下の出典はここ
---------------------
Layouts And Components
To use a default layout, you can add var $layout = 'default'; to the application_controller.
To override the default layout set $layout in your action controller or when you render the action:
$this->render(array('action'=>'long_goal','layout'=>'spectacular'));
1.コントラーラ全体に適用
コントローラ全体に適用する場合には、コントローラのメンバー変数として「$layout」を定義して、前記メンバー変数にレイアウトを指定する。例えばレイアウトを「default.tpl」にしたい場合には、「default」と前記メンバー変数に設定すれば良い。
「default.tpl」と設定するとレイアウトを正しく適用できなくので注意する事。(10分位悩みました)
2.アクション毎に適用
render()関数のパラメータとして、キーを「layout」、前記キーの値に例えば「spectacular」と設定した連想配列を設定すると、render()関数で実行するアクションで「spectacular」レイアウトを適用する事ができる。
以下の出典はここ
---------------------
Layouts And Components
To use a default layout, you can add var $layout = 'default'; to the application_controller.
To override the default layout set $layout in your action controller or when you render the action:
$this->render(array('action'=>'long_goal','layout'=>'spectacular'));
Form Helpers のドキュメントはここ
例えば、Form Helpers には、以下のメソッドなどが用意されている。
・text_field
・file_field
・hidden_field
・password_field
・radio_button
・check_box
・text_area
・select
例えば、Form Helpers には、以下のメソッドなどが用意されている。
・text_field
・file_field
・hidden_field
・password_field
・radio_button
・check_box
・text_area
・select
beforeFileter, afterFilter, aroundFilter などがある。
フィルターチェインのスキップや、フィルターの適用条件なども設定できる。
以下の出典はここ
-------------------------------------------
Action Controller Filters
Filters enable controllers to run shared pre and post processing code for its actions. These filters can be used to do authentication, caching, or auditing before the intended action is performed. Or to do localization or output compression after the action has been performed.
Filters have access to the request, response, and all the instance variables set by other filters in the chain or by the action (in the case of after filters). Additionally, it's possible for a pre-processing beforeFilter to halt the processing before the intended action is processed by returning false or performing a redirect or render. This is especially useful for filters like authentication where you're not interested in allowing the action to be performed if the proper credentials are not in order.
Filter inheritance
Controller inheritance hierarchies share filters downwards, but subclasses can also add new filters without affecting the superclass. For example:
class BankController extends AkActionController
{
function __construct()
{
$this->beforeFilter('_audit');
}
function _audit(&$controller)
{
// record the action and parameters in an audit log
}
}
class VaultController extends BankController
{
function __construct()
{
$this->beforeFilter('_verifyCredentials');
}
function _verifyCredentials(&$controller)
{
// make sure the user is allowed into the vault
}
}Now any actions performed on the BankController will have the audit method called before. On the VaultController, first the audit method is called, then the _verifyCredentials method. If the _audit method returns false, then _verifyCredentials and the intended action are never called.
Filter types
A filter can take one of three forms: method reference, external class, or inline method. The first is the most common and works by referencing a method somewhere in the inheritance hierarchy of the controller by use of a method name. In the bank example above, both BankController and VaultController use this form.
Using an external class makes for more easily reused generic filters, such as output compression. External filter classes are implemented by having a static filter method on any class and then passing this class to the filter method. Example:
class OutputCompressionFilter
{
function filter(&$controller)
{
$controller->response->body = compress($controller->response->body);
}
}
class NewspaperController extends AkActionController
{
function __construct()
{
$this->afterFilter(new OutputCompressionFilter());
}
}The filter method is passed the controller instance and is hence granted access to all aspects of the controller and can manipulate them as it sees fit.
Filter chain ordering
Using beforeFilter and afterFilter appends the specified filters to the existing chain. That's usually just fine, but some times you care more about the order in which the filters are executed. When that's the case, you can use prependBeforeFilter and prependAfterFilter. Filters added by these methods will be put at the beginning of their respective chain and executed before the rest. For example:
class ShoppingController extends AkActionController
{
function __construct()
{
$this->beforeFilter('verifyOpenShop');
}
}
class CheckoutController extends AkActionController
{
function __construct()
{
$this->prependBeforeFilter('ensureItemsInCart', 'ensureItemsInStock');
}
}The filter chain for the CheckoutController is now ensureItemsInCart, ensureItemsInStock, verifyOpenShop. So if either of the ensure filters return false, we'll never get around to see if the shop is open or not.
You may pass multiple filter arguments of each type.
Around filters
In addition to the individual before and after filters, it's also possible to specify that a single object should handle both the before and after call. That's especially useful when you need to keep state active between the before and after, such as the example of a benchmark filter below:
class WeblogController extends AkActionController
{
function __construct()
{
$this->aroundFilter(new BenchmarkingFilter());
}
// Before this action is performed, BenchmarkingFilter->before($controller) is executed
function index()
{
}
// After this action has been performed, BenchmarkingFilter->after($controller) is executed
}
class BenchmarkingFilter
{
function before(&$controller)
{
start_timer();
}
function after(&$controller)
{
stop_timer();
report_result();
}
}
Filter chain skipping
Some times its convenient to specify a filter chain in a superclass that'll hold true for the majority of the subclasses, but not necessarily all of them. The subclasses that behave in exception can then specify which filters they would like to be relieved of. Examples
class ApplicationController extends AkActionController
{
function __construct()
{
$this->beforeFilter('authenticate');
}
}
class WeblogController extends ApplicationController
{
// will run the authenticate filter
}
class SignupController extends AkActionController
{
function __construct()
{
$this->skipBeforeFilter('authenticate');
}
// will not run the authenticate filter
}
Filter conditions
Filters can be limited to run for only specific actions. This can be expressed either by listing the actions to exclude or the actions to include when executing the filter. Available conditions are only or except, both of which accept an arbitrary number of method references. For example:
class Journal extends AkActionController
{
function __construct()
{ // only require authentication if the current action is edit or delete
$this->beforeFilter(array('_authorize'=>array('only'=>array('edit','delete')));
}
function _authorize(&$controller)
{
// redirect to login unless authenticated
}
}
フィルターチェインのスキップや、フィルターの適用条件なども設定できる。
以下の出典はここ
-------------------------------------------
Action Controller Filters
Filters enable controllers to run shared pre and post processing code for its actions. These filters can be used to do authentication, caching, or auditing before the intended action is performed. Or to do localization or output compression after the action has been performed.
Filters have access to the request, response, and all the instance variables set by other filters in the chain or by the action (in the case of after filters). Additionally, it's possible for a pre-processing beforeFilter to halt the processing before the intended action is processed by returning false or performing a redirect or render. This is especially useful for filters like authentication where you're not interested in allowing the action to be performed if the proper credentials are not in order.
Filter inheritance
Controller inheritance hierarchies share filters downwards, but subclasses can also add new filters without affecting the superclass. For example:
class BankController extends AkActionController
{
function __construct()
{
$this->beforeFilter('_audit');
}
function _audit(&$controller)
{
// record the action and parameters in an audit log
}
}
class VaultController extends BankController
{
function __construct()
{
$this->beforeFilter('_verifyCredentials');
}
function _verifyCredentials(&$controller)
{
// make sure the user is allowed into the vault
}
}Now any actions performed on the BankController will have the audit method called before. On the VaultController, first the audit method is called, then the _verifyCredentials method. If the _audit method returns false, then _verifyCredentials and the intended action are never called.
Filter types
A filter can take one of three forms: method reference, external class, or inline method. The first is the most common and works by referencing a method somewhere in the inheritance hierarchy of the controller by use of a method name. In the bank example above, both BankController and VaultController use this form.
Using an external class makes for more easily reused generic filters, such as output compression. External filter classes are implemented by having a static filter method on any class and then passing this class to the filter method. Example:
class OutputCompressionFilter
{
function filter(&$controller)
{
$controller->response->body = compress($controller->response->body);
}
}
class NewspaperController extends AkActionController
{
function __construct()
{
$this->afterFilter(new OutputCompressionFilter());
}
}The filter method is passed the controller instance and is hence granted access to all aspects of the controller and can manipulate them as it sees fit.
Filter chain ordering
Using beforeFilter and afterFilter appends the specified filters to the existing chain. That's usually just fine, but some times you care more about the order in which the filters are executed. When that's the case, you can use prependBeforeFilter and prependAfterFilter. Filters added by these methods will be put at the beginning of their respective chain and executed before the rest. For example:
class ShoppingController extends AkActionController
{
function __construct()
{
$this->beforeFilter('verifyOpenShop');
}
}
class CheckoutController extends AkActionController
{
function __construct()
{
$this->prependBeforeFilter('ensureItemsInCart', 'ensureItemsInStock');
}
}The filter chain for the CheckoutController is now ensureItemsInCart, ensureItemsInStock, verifyOpenShop. So if either of the ensure filters return false, we'll never get around to see if the shop is open or not.
You may pass multiple filter arguments of each type.
Around filters
In addition to the individual before and after filters, it's also possible to specify that a single object should handle both the before and after call. That's especially useful when you need to keep state active between the before and after, such as the example of a benchmark filter below:
class WeblogController extends AkActionController
{
function __construct()
{
$this->aroundFilter(new BenchmarkingFilter());
}
// Before this action is performed, BenchmarkingFilter->before($controller) is executed
function index()
{
}
// After this action has been performed, BenchmarkingFilter->after($controller) is executed
}
class BenchmarkingFilter
{
function before(&$controller)
{
start_timer();
}
function after(&$controller)
{
stop_timer();
report_result();
}
}
Filter chain skipping
Some times its convenient to specify a filter chain in a superclass that'll hold true for the majority of the subclasses, but not necessarily all of them. The subclasses that behave in exception can then specify which filters they would like to be relieved of. Examples
class ApplicationController extends AkActionController
{
function __construct()
{
$this->beforeFilter('authenticate');
}
}
class WeblogController extends ApplicationController
{
// will run the authenticate filter
}
class SignupController extends AkActionController
{
function __construct()
{
$this->skipBeforeFilter('authenticate');
}
// will not run the authenticate filter
}
Filter conditions
Filters can be limited to run for only specific actions. This can be expressed either by listing the actions to exclude or the actions to include when executing the filter. Available conditions are only or except, both of which accept an arbitrary number of method references. For example:
class Journal extends AkActionController
{
function __construct()
{ // only require authentication if the current action is edit or delete
$this->beforeFilter(array('_authorize'=>array('only'=>array('edit','delete')));
}
function _authorize(&$controller)
{
// redirect to login unless authenticated
}
}
Akelosのテンプレートファイルで、以下のようにフォームのinput要素を出力する場合において、「level」が数値で「0」の場合に表示が空となる。
<?php echo $active_record_helper->input('user', 'level')?>
上記のように記述し「user」モデルの「level」が「0」の場合、出力されるHTMLは以下のようになる。
<input id="user_level" name="user[level]" size="30" type="text" />
本当は、以下のようになって欲しいのだが。
<input id="user_level" name="user[level]" size="30" type="text" value="0" />
つまり、「0」の場合に「value」が設定されない問題があった。
そこで、以下のように修正した。
◎変更箇所
lib\AkActionView\helpers\tag_helper.php(105L近辺)
◎変更前
if(empty($value) && !is_string($value)){
◎変更後
if(empty($value) && !is_numeric($value)){
多分、これで問題ないと思う。
<?php echo $active_record_helper->input('user', 'level')?>
上記のように記述し「user」モデルの「level」が「0」の場合、出力されるHTMLは以下のようになる。
<input id="user_level" name="user[level]" size="30" type="text" />
本当は、以下のようになって欲しいのだが。
<input id="user_level" name="user[level]" size="30" type="text" value="0" />
つまり、「0」の場合に「value」が設定されない問題があった。
そこで、以下のように修正した。
◎変更箇所
lib\AkActionView\helpers\tag_helper.php(105L近辺)
◎変更前
if(empty($value) && !is_string($value)){
◎変更後
if(empty($value) && !is_numeric($value)){
多分、これで問題ないと思う。

































