CakePHP

CakePHP findAll の条件に IN 演算子を使う

1

CakePHP の findAll の条件に IN 演算子には下記のように条件を指定すればOKです。

$this->model->findAll(array('field IN (1,2,3)'));
または、

$params = array(1,2,3);
$this->model->findAll(array('field' => $params));

配列で渡せば勝手に IN 演算子を使用してくれるんですね。

CakePHP HTML ヘルパーで textarea を出力する

1

CakePHP の HTML ヘルパーでテキストエリアを出力するには下記のように書きます。

<?php echo $html->textarea("Model/field", array("cols"=>20, "rows"=>5, "value"=>"hoge")); ?>checkbox や radio などと違って第2引数に HTML 属性値がくることに注意が必要です。

array("value"=>"hoge") などと書くことにより初期値を入れることができます。

CakePHP HTMLヘルパーで checkbox を表示する

1

HTMLヘルパーで checkbox を表示するには下記のように書きます。
<?php echo $html->checkbox('Model/field', null, array('value'=>1)); ?>
出力される HTML は下記のようになります。
(実際は1行で出力されますが改行入れています)

<input type="hidden" name="data[Model][field]"  value="0" id="ModelField_" /
<input type="checkbox" name="data[Model][field]" value="1" id="ModelField"  />

checkbox と同じ名前の hidden を勝手に作ってくれるのでチェックされていなくても必ず $this->data["Model"]["field"] には値が帰ってくるのでうれしいかも。

ちなみに第2引数は checkbox では使用されていませんでした。
他のメソッドと統一するためにあるのでしょう。

第3引数に

array('checked'=>1) or
array('checked'=>true) or
array('checked'=>'checked')

などとするとデフォルトでチェックが入ります。

ちなみに HTML_QuickForm のように勝手に label タグで囲んではくれないので、チェックボックスの後ろに書かれた項目名などをクリックしてもチェックされるようにしたければ自分で label タグを書く必要があります。checkbox の ID は ModelField のようになるので、
<label for="ModelField"><?php echo $html->checkbox('Model/field', null, array('value'=>1)); ?>項目名</label>

とすれば「項目名」のテキストをクリックしてもチェックすることができるようになります。

CakePHP cakeError で日本語メッセージを表示できない

0

ビューに直接メッセージを日本語で書けば表示できるのですが、
動的にメッセージを変えたいような場合に、

$params = array( array('message'=>'エラーです') );
$this->cakeError('foo', $params);

とし cakeError に日本語のメッセージをパラメータとして渡しても表示できません。
原因は /cake/libs/error.php のコンストラクタで

$clean = new Sanitize();
$messages = $clean->paranoid($messages, $allow);

となっていて、パラメータをサニタイズしていて半角英数字以外は削除されてしまいます。
ちなみに Sanitize::paranoid メソッドは
/cake/libs/sanitize.php

function paranoid($string, $allowed = array()) {
    $allow = null;
    if (!empty($allowed)) {
        foreach($allowed as $value) {
            $allow .= "\\$value";
        }
    }

    if (is_array($string)) {
        foreach($string as $key => $clean) {
            $cleaned[$key] = preg_replace("/[^{$allow}a-zA-Z0-9]/", "", $clean);        }
    } else {
        $cleaned = preg_replace("/[^{$allow}a-zA-Z0-9]/", "", $string);
    }
    return $cleaned;
}

のようになっています。半角英数字と $allow で許可した文字以外は削除されます。

前回の投稿「cakeError でエラー処理」のように自分で cakeError 処理を書いた場合には /app/error.php でコンストラクタを上書きして問題の部分をコメントアウトすることにより、日本語を表示することができるようになります。

/cake/libs/error.php の __construct メソッドを丸ごと /app/error.php にコピペして
parent::__construct();
$messages = $clean->paranoid($messages, $allow);の2行をコメントアウト

こうすることにより日本語を表示することができるようになりました。

※サニタイズ処理をコメントアウトしていますので、その点は十分に注意が必要です。

CakePHP cakeError でエラー処理

1

CakePHP でエラー処理をさせるのに cakeError を使ってみました。
致命的なエラーのときに、メールを送信したりログを記録したりするのに使えるかと思います。

/app/error.php を作成

class AppError extends ErrorHandler
{
    function foo($params){
        // ここにエラー処理を書く

        // $params を展開
        extract($params);

        // view のディレクトリを指定
        $this->controller->viewPath='errors';

        $this->controller->set('message', $message);
        $this->controller->render('foo');
        exit();
    }
}

エラー用のビューを app/views/errors/foo.thtml に作成

呼び出し方は第1引数にメソッド名、第2引数にメソッドに渡すパラメータ

$params = array( array('message'=>'Error!') );
$this->cakeError('foo', $params);

$params の指定方法にちょっとだけ注意が必要です。

CakePHP DISTINCT の使用方法

1

cakebaker ? Using distinct and count with CakePHP

CakePHP で DISTINCT を使いたい時の方法が紹介されていました。

$this->User->find(null, "COUNT(DISTINCT User.city) AS 'count'");

find は /cake/libs/model/model_php5.php
function find($conditions = null, $fields = null, $order = null, $recursive = null)
と定義されています。
この $fields をうまく使っているということですね。

CakePHP コントローラのメソッドをURLから実行させない

0

コントローラにアクション以外のメソッドを書かないのが一番いいのかもしれません。
ただ、どうしても書きたいという場合にはメソッド名にアンダーバー “_” を付けるとURLからアクセスできなくなります。

試しに posts_controller.php_foo というメソッド名を作り /posts/_foo/ にアクセスしてみると
Private Method in PostsController
You are seeing this error because the private class method _foo should not be accessed directly.

とプライベートメソッドなのでアクセスできませんよというエラーメッセージが出力されました。

しかしこのメッセージってあまりよくないのではと思い、試しに DEBUG=0 とデバッグモードを本番環境用にしたところ、

Not found
The requested address posts/_foo/ was not found on this server.

となりました。やはり考えてますよねそれくらい。

ちなみにエラーメッセージは
/cake/libs/view/templates/errors/
にエラーの種類によって15のテンプレートが用意されています。
自分で Not found などのエラーを修正したい場合は
/cake/libs/view/templates/errors/error404.thtml

/app/views/errors/error404.thtml
にコピーして修正すればそちらのテンプレートが使用されます。

CakePHP の日本語マニュアルに書かれている

メンバ関数を protected にして見えるようにするには、コントローラアクション名を ‘-’ ではじめてください。(訳注:将来の仕様???)
メンバ関数を private にするためには、コントローラアクション名を ‘–’ ではじめてください。(訳注:将来の仕様???)

というのはこれのことなのかな?
ただ、”_” ではなく “-” になっている。(英語のマニュアルも同様に “-” でした。)

CakePHP 日本語マニュアル
C.4. コントローラ(Controllers)

CakePHP マニュアル(英語)
CakePHP Manual

CakePHP htmlヘルパーでラジオボタンを離れた場所に分けて書く方法

1

html ヘルパーでラジオボタンを書く場合
<?php echo $html->radio('Model/field', array('1'=>'option1','2'=>'option2', '3'=>'option3')); ?>
のように書くと、ラジオボタンを横に並べて表示させることができます。

ただ、デザインによってはテーブルなどを使用していたり縦に並べたりして、ひとつづつ表示させたいときもあると思います。

その場合は

<?php echo $html->radio('Model/field', array('1'=>'option1')); ?>
<?php echo $html->radio('Model/field', array('2'=>'option2')); ?>
<?php echo $html->radio('Model/field', array('3'=>'option3')); ?>

とすれば、それぞれのボタンを希望の位置に表示させることができます。

CakePHP html ヘルパーでラジオボタンの選択状態 (checked) を指定する方法

1

html ヘルパーを使用してラジオボタンの選択状態 (checked) を指定する方法です。

下記のようにすると option2 にチェックがつきます。
<?php echo $html->radio('Model/field', array('1'=>'option1','2'=>'option2', '3'=>'option3'), null, array('value'=>'2'), false); ?>

第4パラメータの array(‘value’=>’2′) でチェックするボタンを指定しています。
キーの ‘value’ は固定で、値の’2′ の方をチェックしたいラジオボタンの value 属性の値と同じものを指定すれば、そのボタンがチェックされます。

デフォルトや以前入力された状態を表示するために使用できそうです。

CakePHP html ヘルパーでラジオボタンを表示する

0

htmlヘルパーで radio ボタンを表示させるには下記のようにします。
下記の例では3つのラジオボタンを表示しています。
<?php echo $html->radio('Model/field', array('1'=>'option1','2'=>'option2', '3'=>'option3'), ' | ', array('onchange'=>'alert(this.value)'), false); ?>

表示される HTML は下記のようになります。
(実際には1行で出力されますが改行を入れています)

<input type="radio" name="data[Model][field]" id="field_1" onchange="alert(this.value)" value="1"  />option1 |
<input type="radio" name="data[Model][field]" id="field_2" onchange="alert(this.value)" value="2"  />option2 |
<input type="radio" name="data[Model][field]" id="field_3" onchange="alert(this.value)" value="3"  />option3 |

radio メソッド
string radio(string $fieldName, arrray $options [,string $inbetween=null [,array $htmlAttributes=array() [,bool $return=false ]]])

$fieldName
name属性の値
$option
array(‘value’=>’表示名’);
value は value=”value” になり、表示名はラジオボタンの後ろに表示される文字名
$inbetween
ラジオボタンの間に表示される文字列
$htmlAttributes
html の属性 array(‘属性名’=>’値’)で指定する
$return
ヘルパーの自動出力を抑止する(参考:ヘルパーの出力を echo を使わずに出力する方法)
Go to Top