Posts tagged PHP

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 が付かないのではまらないように。

OpenPNE コンテンツをセンター寄せにする

0

OpenPNE のデザインは左寄せなのですが、これをセンター寄せに変更したいという要望がありました。
最初は CSS に
.ext_sub_container { width: 720px;margin: 0px auto; }を追加してみたのですが、やはり IE ではうまく表示できません。
そこでテンプレートを見直すと
inc_header.tpl 339行目
<div align="left">というを
<div align="center">に変更したらうまく行きました。

ちなみに OpenPNE テンプレートのカスタマイズ でも書きましたが
/openpne/webapp/modules/pc/templates/inc_header.tpl
/opnepne/webapp_ext/modules/pc/templates/inc_header.tpl
コピーしてからカスタマイズすると元のファイルを残したままカスタマイズできるのでお勧めです。
その場合は /openpne/config.php
define('USE_EXT_DIR', false);
define('USE_EXT_DIR', true)に変更するのをお忘れなく。

北海道旅行 その1 モエレ沼公園

1

イサム・ノグチが設計したモエレ沼公園
新千歳空港からレンタカーで1時間弱くらいで着きました。駐車場は広大で無料でした。
園内もかなり広く1日使ってゆっくりするのがいいかもしれません。
うちの子供は遊具に大興奮して遊んでいました。

ガラスのピラミッド
ガラスのピラミッド

海の噴水
海の噴水

テトラマウンド
テトラマウンド

ブランコなど
遊具

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 されれいます。

OpenPNE ユーザID からユーザ情報を取得するグローバル関数

1

OpenPNE をカスタマイズしていてユーザID からユーザのニックネームなど簡単に取得できないかと調べてみると、色々なグローバル関数がありました。

openpne/webapp/lib/db/member.php 内で各種定義されています。

ユーザ情報のよく使う部分のみを取得する

関数名
db_member_c_member4c_member_id_LIGHT($c_member_id)
引数
int $c_member_id ユーザID
戻り値
array ユーザ情報

引数はユーザ IDで、ユーザ情報が連想配列で戻されます。

array(
    'c_member_id' => 'ユーザID',
    'nickname' => 'ニックネーム',
    'image_filename' => '画像ファイル名'
)

ニックネームはそのままテンプレートで表示できます。
画像ファイル名は以前のエントリの「OpenPNE 画像の保存、表示方法」や「OpenPNE 画像を色々なサイズで表示する」を参考に表示させることができます。

ユーザ情報を取得する

関数名
db_member_c_member4c_member_id($c_member_id, $is_secure = false, $with_profile = false, $public_flag = ‘public’)
引数
int $c_member_id ユーザID
bool $is_secure `c_member_secure`の項目を取得するかどうか
bool $with_profile `c_member_profile`の項目を取得するかどうか
string $public_flag プロフィール項目を取得する場合の公開設定(public, friend, private)
戻り値
array ユーザ情報

その他

まだまだ色々な関数があります。興味ある方はソースを調べてみるとよいかと思います。

OpenPNE 画像を色々なサイズで表示する

1

以前書いたエントリ「OpenPNE 画像の保存、表示方法 」で、OpenPNE にアップロードした画像の表示方法を紹介しました。

表示方法は下記のとおりです。
<img src=&qt;({t_img_url filename=$pet.image1 w=180 h=180})&qt;>

しかし、この方法では 240×240 のような画像が表示できませんでした。
ソースを追ってみると設定ファイルで許可するサイズを設定するところがありました。

openpne/config.php
$GLOBALS['_OPENPNE_IMG_ALLOWED_SIZE'] = array('76x76', '120x120', '180x180');

この配列に ’240×240′ を追加すれば 縦か横の長い方が 240px の写真が表示できます。
また、
$GLOBALS['_OPENPNE_IMG_ALLOWED_SIZE'] = array();
のように空の配列にすれば制限がなくなり、自由に大きさを指定できます。
ただ、制限はかけておいた方がいいでしょう。

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

1

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

$this->Model->cacheQueries = false;

Go to Top