Posts tagged CakePHP

CakePHP Model::generateList メソッドの {n}

2

CakePHP で select タグを生成する際に generateList メソッドをよく使います。

ちなみに使い方は下記の通りです。
$this->Model->generateList($conditions, $order,$limit, $keyPath, $valuePath);
$coditions :検索条件
$order :ソートの指定
$limit :取り出す数
$keyPath :配列のキーにするフィールド
$valuePath :配列の値にするフィールド

この $keyPath と $valuePath の指定方法が曲者で
{n}.Model.field
のようにモデル名の前に「{n}.」をつけなくては正しくデータを取得できません。

この「{n}」というのがなんなのかが気になり調べてみました。
詳しくは下記リンク先を参照していただくと分かります。
{n} ? – Cake PHP | Google グループ

以下実際に CakePHP のコードを調べてみたことをまとめます。

  • generateList メソッドでは検索条件などによって findAll する
  • findAll したデータから Set::extract メソッドを使用して該当するフィールドデータのみ抜き出す
  • Set::extract メソッドは配列以外にもオブジェクトからも extract できるように設計されている
  • 配列の場合はモデル名の前に「{n}」があるかどうかで判定している

という感じのようです。

ちなみに Set クラスは /cake/libs/set.php で定義されていて、コメントを見ると配列用のライブラリクラスのようです。

また、generateList で $keyPath, $valuePath を指定しなかった場合は下記のようになるようです。

  • $keyPath には モデルで指定した $primaryKey を使用
  • $primaryKey の指定がなければ ‘id’ フィールドを使用
  • $valuePath には モデルで指定した $displayField を使用
  • $displayField の指定がなければ ‘title’ フィールドが存在すれば ‘title’ フィールドを使用
  • ‘title’ フィールドが存在しなければ ‘name’ フィールドを使用
  • ‘title’ フィールドも ‘name’ フィールドも存在しなければ ‘id’ フィールドを使用

フィールド名の付け方も重要ですね。

CakePHP ファイルアップロードするコンポーネント

2

CakePHP でファイルアップロードを簡単に行うコンポーネントです。
ReverseFolds – CakePHP File Uploads

データベースにファイル名、MIMEタイプ、サイズなどを記録し、ファイルは指定したディレクトリへアップロードするようになっています。

ビューにファイルアップロード用のタグを設置

<input type='file' name='userfile[]'/>
複数配置したいときは

<input type='file' name='userfile[]'/>
<input type='file' name='userfile[]'/>

コントローラに使用するコンポーネントを追加

var $components = array('FileHandler');

アップロード処理

$this->FileHandler->setDebugLevel(1);
$this->FileHandler->setRequired(0);
$this->FileHandler->setHandlerType('db');
$this->FileHandler->setDbModel('FileUpload');
$uploadDir = 'path/to';    // アップロードするディレクトリを指定
if ($this->FileHandler->upload('userfile', $uploadDir)) {
    echo 'アップロード成功';
} else {
    echo 'アップロード失敗';
}

実際の処理などはリンク先からダウンロードしたファイルにコンポーネントの他に、ビュー、コントローラ、モデル、SQL と必要なものは入っているのでソースを見てみるとすぐに分かると思います。

アップロードされるファイルは $uploadDir で指定したディレクトリ内にユニークなディレクトリ名を作成してそのディレクトリ内に元のファイル名で保存してくれます。

その他のメソッド

アップロードできるファイルタイプを限定するメソッド
void setAllowedMime( array $mimeTypes )

ファイルの最大容量を設定するメソッド
void setMaxSize( int $size )
などもあります。

CakePHP Pagination まとめ

2

CakePHP の Pagination に関してまとめてみました。

コントローラでコンポーネント、ヘルパーに Pagination を指定

// 使用コンポーネント名
var $components = array('Pagination');
// 使用ヘルパー名
var $helpers = array('Pagination');

コントローラの一覧表示するアクションでの一覧表示取得方法

$this->Pagination->modelClass = 'Model'; // 使用するモデル
$this->Pagination->sortBy = 'created';	 // デフォルトのソートするフィールド名
$this->Pagination->direction = 'DESC';	 // デフォルトの昇順、降順を指定
$this->Pagination->show = 10;			 // 1ページに表示する件数
$conditions = array(); 					 // 検索条件
list($order,$limit,$page) = $this->Pagination->init($conditions);
$lists = $this->Model->findAll($conditions, $fields, $order, $limit, $page, $recursive);

ビューでのヘルパー使用準備

ビューで Pagination ヘルパーを使用できるようにする
< ?php $pagination->setPaging($paging); ?>

ビューでの総件数と表示している件数の表示

< ?php echo $pagination->result('検索結果:', '/', '?'); ?>件
上記のように指定すると「検索結果:1?10/5253件」と表示されます。

ソートするフィールドを変更するリンクを表示する

< ?php echo $pagination->sortBy('field_name', 'フィールド名', 'ModelName'); ?>
field_name にソートするフィールド名、
フィールド名にリンクに表示する名前、
ModelName にはフィールド名が属するモデル名
を指定します。
モデル名は $this->Pagination->modelClass と同じ場合には省略可能です。

また、sortBy メソッドは
veiws/heplers/pagination.php
function sortBy ($value, $title=NULL, $Model=NULL,$escapeTitle=true,$upText=' ^',$downText=' v')
のように定義されています。見て分かるとおり第5、6引数を指定することにより、ソートしたときのリンクのフィールド名につく「^」「v」の文字を変更することができます。

select タグによってソートを指定したいときは sortBySelect メソッドがあります。
function sortBySelect($sortFields, $t='Sort By: ',$upText=' ^',$downText=' v')

CakePHP 携帯でセションを有効にする

2

CakePHP で携帯サイトの開発をしています。
ドコモなどはクッキーが使用できないのでセションID を URL で引き継がないといけないのですが、PC サイトではクッキーでセションID を保持したいところです。

携帯サイトと PC サイトが共存しているときの携帯用のビューを表示させる方法は下記が参考になります。
CakePHP 携帯用ビューを表示する | Shin x blog

また、携帯でのアクセス時にクッキーを使用せずにセション を保持するのは下記が参考になります。
Docomoとセッション フォーラム – CakePHP Users in Japan

私は上記の方法に
ini_set('session.use_trans_sid', 1);を入れて使用しています。

全てのリンク、フォームにセションID が付加されるので便利です。
ただリダイレクトするときだけ、
$this->redirect('/controller/action/'.session_name().'='.session_id());のようにセションIDを入れました。

あとビューを書くときに覚えておくとよいのが、ini_set(‘session.use_trans_sid’, 1); を指定したときにリンクを http:// から始まる URL を書くとセションID は当然ですが付加されません。相対パス、絶対パスなどの自サイト内へのリンクのみセションIDが付加されます。
自サイト内のリンクに http:// から書くとセションID が付かないのではまらないように。

CakePHP findAll で INNER JOIN する方法

1

開発中の CakePHP の案件でどうしても INNER JOIN する必要があり、かといって SQL を直接書くのは他のコンポーネントとの兼ね合いでできるだけ避けたい(というより無理)な状況だったので、絶対何か方法があるだろうと思いソースを調べたのでメモしておきます。

/cake/libs/model/model_php5.php の findAll メソッドに

$queryData = array('conditions' => $conditions,
    'fields'    => $fields,
    'joins'     => array(),
    'limit'     => $limit,
    'offset'    => $offset,
    'order'     => $order
);

というのがあり、’joins’ に 空の配列を入れている。
この ‘joins’ の使い方を調べたら、

array(
    "type" => "INNER",
    "alias" => "",
    "table" => INNER JOIN するテーブル,
    "conditions" => INNER JOIN の ONに指定する条件,
);

という配列を入れると INNER JOIN してくれるようです。

ただ、findAll の中で joins に空配列を入れているので、findAll を実行するときのパラメータに joins を指定しても無視されてしまう。
そこで、モデルの beforeFind メソッドを使用することにした。このメソッドは findAll の実行する前に呼ばれるメソッドです。

findAll を実行するモデルに次の beforeFind を定義

function beforeFind(&$queryData) {
    $queryData["joins"][] = array(
        "type" => "INNER",
        "alias" => "",
        "table" => "`model_name`",
        "conditions" => array("model_name.field=model_name2.field2"),
    );
    return true;
}

これで実行された SQL を確認すれば INNER JOIN されれいます。

CakePHP 保存したデータをすぐに find したい場合キャッシュを OFF にする

1

CakePHP で保存したデータをすぐにfind するとキャッシュが効いている為に保存したばかりのデータを取得することができません。
その場合はキャッシュを OFF にすることにより新しいデータを取得することができます。

$this->Model->cacheQueries = false;

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

0

前回の投稿の「CakePHP findAll の条件に IN 演算子を使う」のつづきで、NOT IN 演算子を使用するときに少し調べたのでメモしておきます。

$this->model->findAll('field NOT IN (1, 2, 3)');
または、
$this->model->findAll(array('NOT' => array('field' => array(1, 2, 3))));
で出来ました。

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>

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

Go to Top