Posted on

CakePHPのHasAndBelongsToManyを使う

多対多のデータを扱うのにHasAndBelongsToManyをモデルで指定してあげると
簡単にデータの取り出しや保存が出来ました。

今回は社員が複数の部署に属すという仕様で使いました。
テーブルは次のようにしました。
parts(部署テーブル)、
users(社員テーブル)、
parts_users(部署・社員連携テーブル)
部署・社員連携テーブルは繋げたいテーブルを「_」で連結させてテーブル名とします。
parts_usersのフィールドは「part_id、user_id」となります。

次にPartsUserモデルを作っていないとエラーになるので作っておきます。

class PartsUser extends AppModel
{
var $name = 'PartsUser';
var $useTable = 'parts_users';
}

Userモデルで

class User extends AppModel
{
var $name = 'User';
var $useTable = 'users';
var $hasAndBelongsToMany = array('Part');
}

と記述してあげるとUserモデルでセレクトして得られた配列に
所属している部署全てが取得できています。

データの取得はこれですんなりと上手くいったのですがデータの保存が
あまり資料が無くはまりました。
データをセレクトで取得した形式でsaveしてあげても上手く保存が出来ません。
ではどういう配列構造で保存してあげればいいのか、

$this->data['Part']['Part'][0] = 部署番号
$this->data['Part']['Part'][1] = 部署番号
$this->data['Part']['Part'][2] = 部署番号
・
・
・

という感じにデータを持たしてあげるとparts_usersテーブルに社員と部署を
連携したデータを保存してくれます。

Posted on

CakePHPで携帯サイト作成時に注意したところ

今回、携帯サイトを作るにあたって各携帯会社によって挙動が違うくて詰まった箇所や携帯サイト独自の作り方をしたところをメモで残そうと思います。

まず携帯会社によって入力フォームの入力文字をデフォルトで切り替える方法です。
app/app_controller.phpのbeforeFilter()で
各携帯メーカーによってモードを変えます

//  DoCoMo 用
if (ereg( "DoCoMo", $_SERVER["HTTP_USER_AGENT"] )) {
$mode = "istyle";
$mode_1 = 1;
$mode_2 = 2;
$mode_3 = 3;
$mode_4 = 4;
//  ezweb 用
} elseif (ereg( "UP\.Browser", $_SERVER["HTTP_USER_AGENT"] )) {
$mode = "format";
$mode_1 = "*M";
$mode_2 = "*M";
$mode_3 = "*m";
$mode_4 = "*N";
//  J-Phone 用
} elseif (ereg( "J-PHONE", $_SERVER["HTTP_USER_AGENT"] )
|| ereg( "SoftBank", $_SERVER["HTTP_USER_AGENT"] )
|| ereg( "Vodafone", $_SERVER["HTTP_USER_AGENT"] )) {
$mode = "mode";
$mode_1 = "hiragana";
$mode_2 = "katakana";
$mode_3 = "alphabet";
$mode_4 = "numeric";
//  L-mode 用
} elseif (ereg( "L-mode", $_SERVER["HTTP_USER_AGENT"] )) {
$mode = "istyle";
$mode_1 = 1;
$mode_2 = 2;
$mode_3 = 3;
$mode_4 = 4;
//  その他用
} else {
$mode = "istyle";
$mode_1 = 1;
$mode_2 = 2;
$mode_3 = 3;
$mode_4 = 4;
}

上の記述で出来たモードを$this->setでビューに渡して、ビュー側でフォームの属性に上のモードを持たすとデフォルトの入力文字が各携帯会社で「漢」「ア」「1」という形で出るようになります。
ビュー側の例:<?php echo $form->text(‘Delivery.name1’, array(“size”=>8, $mode=>$mode_1)) ?>

次に携帯会社によってgifが使えたりpngが使えたりと違うので携帯会社によってgifを使うかpngを使うか切り替えます。
app/app_controller.phpのbeforeFilter()で

//携帯機種によって画像拡張子を切り替える
$ua = $_SERVER["HTTP_USER_AGENT"];
if(ereg("J-PHONE|Vodafone|UP\.Browser",$ua)){
$this->set("extension", "png");;
}else{
$this->set("extension", "gif");;
}

と振り分けてビューに拡張子を渡してファイル名と拡張子を合体させて出力します。
(注)pngの場合テーブルサイズが指定されていなかったらauの場合に自動で画像を横長にしてしまったのでテーブル幅は指定しておきます。

最後に各携帯会社のブラウザの独自仕様で詰まったところを記述していきます。
・auではラジオボタンの二つの候補の間に他のフォームが入ると二つのラジオの関係性が無くなってしまうので他のフォームを挟まないようにしました。
・docomoで検索をした値をセッションに持たしておいて他のページにいった後に戻って検索をもう一度すると半角スペースを最後に付加する現象が起こって検索が引っ掛からなくなったので検索前に検索文字列をtrim関数で両端の半角スペースを除去しておきました。
・auではブラウザを閉じてもセッションを開放しないので最後のページもしくは最初のページでセッションをdestroyしておきました。

Posted on

CakePHPで携帯サイトを作る

2009/11/09追記

この記事のやり方だとCakePHPのバージョンが上がったら動かなくなったので新しく記事を書きました。
CakePHPで携帯サイトを作成する

今回、携帯サイトをCakePHPで作ったので、そのまとめを覚書でブログに載せておこうと思います。

CakePHPのバージョンは1.2.0.7296を使用しました。

まず.htaccessで
php_flag session.use_trans_sid On
php_flag session.use_cookies Off
これら二つの記述をして実際に動くindex.phpと同じフォルダに配置します。
session.use_trans_sidをオンにするとリンクで移動するところ全てにGETでセッションIDを引き継いでくれるようになり、session.use_cookiesでオフにすることでクッキーの使用をしないようにするというものです。

次にapp/config/core.phpの設定を変更します。
122行目付近の
Configure::write(‘Session.cookie’, ‘CAKEPHP’);
の記述の部分でGETでセッションIDを持たす時の名前を指定できるので任意の違う名前に変えておきます。
149行目付近の
Configure::write(‘Security.level’, ‘medium’);
でセキュリティーのレベルが設定できるのでhighからmediumに落としました。highのままだとsession.use_trans_sidが上手く動かなかったので。
127行目付近の
Configure::write(‘Session.timeout’, ‘120’);
でセッションのタイムアウト時間を設定します。
セキュリティーレベルをmediumに落としたのでhighの時よりセッション時間が10倍(3時間半ぐらい)になってしまったので
ここのセッションタイムアウト時間を小さくしておきます。

それからフォームでサブミットされてジャンプする時にもセッションIDを引き継がないといけないのでapp/app_controller.phpに以下の記述を加えます。

//redirect メソッド書き換え
function redirect($url,$status = null){
//携帯用にリダイレクトのURLの後ろにセッションIDを付けておく
if (strpos($url, "?") === false) {
$url = $url."?".session_name()."=".session_id();
}else{
$url = $url."&".session_name()."=".session_id();
}
parent::redirect($url,$status);
}

と記述してサブミット先のページにGETでセッションIDを渡すようにします。

最後にページャーなどのURLを生成する際にGET条件が「:」「/」で作成される部分をセッションIDをGETで渡す関係で「&」「=」の形で作り変えます。(CakePHP1.2のバージョンからGETの渡し方が「:」「/」となっているので)
修正ファイル:cake/libs/router.phpのfunction url()
851行目付近の

if (!empty($named)) {
foreach ($named as $name => $value) {
$output .= '/' . $name . $_this->named['separator'] . $value;
}
}

の記述を

if (!empty($named)) {
$i = 0;
foreach ($named as $name => $value) {
//$output .= '/' . $name . $_this->named['separator'] . $value;
if ($i == 0) {
$output .= '?' . $name . "=" . $value;
}else{
$output .= '&' . $name . "=" . $value;
}
$i++;
}
}

という風に修正します。これで携帯のセッションがゲットで渡せるようになります。

以上の設定をするとCakePHPを使って携帯サイトの構築が出来ました。
次回はCakePHPで携帯サイトを作成する時に、はまった箇所を書きたいと思います。