ウェブインコ

インコの技術メモ

CakePHP1.3

直前で保存したレコードのID
if($this->Hoge->save($data)){
  $new_id = $this->Hoge->getLastInsertID();
}

ヘルパー内でインナージョイン
  $params = array(
   'conditions' => array(
    'Hoge.contractor_id' => $contractor_id,
    'Hoge.status' => 0,
   ),
   'fields' => array('id', 'Hoge_name'),
   'order' => array('id ASC'),
   'joins' => array(
    array('type' => 'INNER',
     'table' => '`Hoge_details`',
     'alias' => 'HogeDetail',
     'conditions' => '`Hoge`.`id`=`HogeDetail`.`Hoge_id`',
    ),
   ),
  );
  $HogeData = $Hoge->find('all', $params);

全角文字を json_encode してMySQLに保存したら decode できなくなった。
save のときは良いのだけれど、 updateAll の時に発症します。
プログラムを追っていくと、updateAllの方には mysql_real_escape_string() が抜けていることが分かりました。
1) 全角文字があるときは updateAll とは別の手段で一括更新する。(queryやfind,for,save等
2) json_encode() と updateAll() の間に mysql_real_escape_string() でもかましておく。
3) 以下のファイルあたりを修正する。(やめといた方が良い)
 /cake/libs/model/datasources/datasource.php
 /cake/libs/model/datasources/dbo/dbo_mysql.php

ajaxで組み立てたページから遷移してhistorybackで戻ったら元に戻らない(組み立て前の画面になる)
ブラウザによって挙動は異なるが基本的にダメ。
解決方法は以下。

1)historybackを使わない。
    『戻る』ボタンはサーバーに投げて、前にポストした情報を基にサーバー側で再構築し直す。
 更新に必要でなくても構築に必要なものはhiddenで送っておく。
 どんな画面でも再現できるが鬼面倒です。
2)フォームの中身はどのブラウザも復元してくれるので、その内容に基づいて再構築する。
 必要な情報はhiddenに埋めておく。
 ページ読み込み時にformの各値を呼んで反映させる。
 フォーム自体がajaxで呼ばれている場合は 1) が望ましい。
 タイムラグが影響の無い範囲ならこちらでも良い。

フロントと管理画面を分けるとき
public_html と public_html/admin とかでindex.phpの内容かき分けるのでも良いのだけど、自分でapache触れるときは以下の方が閉鎖されて便利かもです。
ウェブルートを webroot に。
ln -s /home/www.hoge.jp/cakephp/app/webroot /home/www.hoge.jp/public_html
ln -s /home/www.hoge.jp/cakephp/app_admin/webroot /www.hoge.jp/public_html/VxBAZ5dI8cyYZn
モデルやコンストを共有するときは以下。
ln -s /home/www.hoge.jp/cakephp/app/models /home/www.hoge.jp/cakephp/app_admin/models
bootstrap.php
App::build(array(
  'models' => array(ROOT.DS.'app'.DS.'models'.DS),
));
config('../../app/config/const');

paginateでgroupを指定するとページングの数字が消える。
$options['group'] = array('url','ymd');
$options['limit'] = 5;
$this->paginate = $options;
$this->set('url_logs', $this->paginate($conditions));
みたいなとき、ページングが消えます。
app_model.php に以下を記述します。
function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null, $extra = array()) {
  $conditions[] ="1 = 1 GROUP BY week, away_team_id, home_team_id";
  $recursive = -1;
  $fields = array('week', 'away_team_id', 'home_team_id');
  return $this->find('all', compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive'));
}

Warning (2): strtotime() [http://php.net/function.strtotime]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/New_York' for 'EDT/-4.0/DST' instead [CORE/cake/libs/cache.php, line 597]

php.ini に以下を書き込んでアパッチ再起動。

date.timezone =Asia/Tokyo

bootstrap.php に関数を書く。
便利だけどあまり見かけないので多用しない方が良いのかな。
ここに直接書いても良いですが、const.php とでも作って置いて以下の記述により呼び出し。
config('const');
例)
// 固定値
define("PAGELIMIT", 10);
// 誕生日年(固定)   
function BirthYear(){
    // minYear=最小年齢 minYear+maxYear=最高年齢
    $now = getdate();
    $data = array('minYear' => $now['year'] -4, 'maxYear' => $now['year'] -96, 'dateFormat'=>'YMD');
    return $data;
}
ビュー
echo $form->input('birthday',BirthYear());

ちょっとしたメモ(自分流儀的な)
・メソッドは全部モデルに。なぜならどこからでも呼び出せるから。
・固定値はbootstrap.phpあたりに。
・コントローラーで処理するようなことをビュー(helper)にさせるのは有りだが、モデルのメソッドを呼ぶ踏み台程度にしたほうが良い。テンプレにプログラムを書きすぎるのは良くないです。
・共通部分はなるべくエレメントに。スマホ版にも転用できるできないで作業は2倍になります。
・(1)javascriptで、PHPから渡す変数を動的に使いたいときにはエレメントに書いて各々食わすのが良いのか、(2)あくまで固定ファイルとして置いておいて、変数はHTML内に1つ置き場を決めておき、JSONで食わす+jqueryで取り出すのが良いのか。
 ファイル呼出順が影響するものが有るかもだから(2)が良いのかな。
・$this->Model->save($this->data)←この形だと悪意によるformへの要素追加があった場合、更新できてしまうので、何かしらワンクッション置いた方が良い。
ex.1)$data['Model']['name']=$this->data['Model']['name'];
ex.2)unset($this->data['Model']['status']);