Archive for 11月, 2007
GoogleMap 特定のキーワードで表示させる
4Google AJAX Search API を使用してキーワードや住所から自分のサイトに Google Map を表示させるメモ
Google AJAX Search API KEY と Google Map API KEY を指定して JavaScript を読み込む
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=Google AJAX Search API KEY" type="text/javascript"></script> <script src="http://maps.google.com/maps?file=api&v=2.x&key=Google Map API KEY" type="text/javascript"></script>
実際の表示部分。 q=キーワードで表示させる地図のキーワード(または住所)を指定する。
<script type="text/javascript"> <!-- var gls; var gMap; function OnLocalSearch() { if (!gls.results) return; var first = gls.results[0]; var point = new GLatLng(parseFloat(first.lat), parseFloat(first.lng)); var zoom = 15; gMap.addControl(new GSmallMapControl()); gMap.addControl(new GMapTypeControl()); gMap.setMapType(G_MAP_TYPE); gMap.setCenter(point, zoom); var marker = new GMarker(point); gMap.addOverlay(marker); GEvent.addListener(marker, "click", function() { marker.openInfoWindowHtml(html); }); } function load() { gMap = new GMap2(document.getElementById("map")); gMap.addControl(new GSmallMapControl()); gMap.addControl(new GMapTypeControl()); gMap.setCenter(new GLatLng(0, 0)); gls = new GlocalSearch(); gls.setCenterPoint(gMap); gls.setSearchCompleteCallback(null, OnLocalSearch); var q = "横浜ランドマークタワー"; gls.execute(q); } //--> </script> <body onLoad="load()"> <div id="map" style="width: 410px; height: 320px"></div> </body>
各 API KEY の取得は下記ページから
Sign-up for an AJAX Search API Key – Google AJAX Search API – Google Code
Sign Up for the Google Maps API – Google Maps API – Google Code
CakePHP 環境によってデータベースを切り替える
2テストデータを入れるなどテストと環境でデータベースを切り替えたいときがあります。
CakePHP でそれをやる方法です。
モデルの $useDbConfig に app/config/database.php で定義されている $default がデフォルトで使用されます。
database.php に $test など使用したいデータベースの分だけ定義を増やし、
それをモデルで
$this->useDbConfig = 'test';
のように指定すればいいだけです。
app/app_model.php のコンストラクタで設定するのが一番簡単かもしれません。
CakePHP 環境に応じてDBの設定を変える | Shin x blog
で色々な方法が紹介されています。
“CakePHPで超簡単スケーラビリティ” フォーラム – CakePHP Users in Japan
また、この $useDbConfig を使用して
「マスターとスレーブのMYSQLサーバがあります。レプリケーション機能で、マスターからスレーブにデータが常にコピーされています。データの更新・追加はマスターに対して行い、データの検索はスレーブで、という場合にはどうすればよいでしょうか?」
というような場合のすごく簡単な方法が紹介されています。
モデルの beforeSave,afterSave,beforeDelete,afterDelete を使用してマスターとスレーブを切り替えています。
CakePHP MySQL で文字化けを防ぐ設定
4MySQL で文字化けを防ぐためには
SET NAMES utf8
のように SET NAMES を実行するのが有効なのですが、これを app/config/database.php で設定する方法です。
'encoding'=>'文字コード'
をデータベースの設定項目に追加してやるだけです。
具体的には app/config/database.php が下記のようになります。
var $default = array( 'driver' => 'mysql', 'connect' => 'mysql_connect', 'host' => 'localhost', 'login' => 'user', 'password' => 'password', 'database' => 'dbname', 'prefix' => '', 'encoding' => 'utf8' );
cake/libs/model/dbo/dbo_mysql.php で下記のように実行されています。
function connect() { (略) if (isset($config['encoding']) && !empty($config['encoding'])) { $this->setEncoding($config['encoding']); } return $this->connected; }
function setEncoding($enc) { return $this->_execute('SET NAMES ' . $enc) != false; }
CakePHP モデルの validation の拡張 同じ項目で違うメッセージを出す
1CakePHP のモデルの validation の拡張のメモの続きです。
同じフォームの項目で違うエラーメッセージを出したいときがあります。
例えばユーザ登録フォームでユーザID がフォーマットエラーなのか、既に使用されているのかなどです。
models/users.php
var $validate = array( 'loginid' => '/^[0-9a-zA-Z]{8}$/', ); function validates($data=array()) { if(empty($data)) { $data = $this->data; } parent::validates($data); // loginid のユニークチェック if ($this->findByLoginid($data["User"]["loginid"])) { $this->invalidate("loginid_unique"); } if (count($this->validationErrors)>0) { return false; } else { return true; } }
既にloginid が登録済みの場合は
$this->invalidate('loginid_unique');
としています。
invalidate に指定するのは実際に存在しないものでも大丈夫なのでそれを使用して view でエラーメッセージを分けて表示します。
views/users/regist.thtml
ID:< ?php echo $html->password('User/loginid'); ?> < ?php echo $html->tagErrorMsg("User/loginid", "IDは英数字8文字で入力してください"); ?> < ?php echo $html->tagErrorMsg("User/loginid_unique", "IDは既に使用されています。他のID を指定してください"); ?>
CakePHP モデルの validation の拡張
1CakePHP のモデルの validation の拡張のメモです。
ユーザ登録フォームなどでパスワードの再確認のバリデーションを行うときの方法です。
views/users/regist.thtml
パスワード:< ?php echo $html->password('User/password'); ?> 確認用パスワード:< ?php echo $html->password('User/password2'); ?> < ?php echo $html->tagErrorMsg('User/password2', 'パスワードが一致しません');
※users テーブルにpassword2 のカラムはなくてかまいません。
models/users.php
function validates($data=array()) { if(empty($data)) { $data = $this->data; } parent::validates($data); if ($data["User"]["password"]!==$data["User"]["password2"]) { $this->invalidate("password2"); } if (count($this->validationErrors)>0) { return false; } else { return true; } }
AppModel クラスの validation メソッドも実行する必要があるので、必ず
parent::validates($data);
を書かないといけません。
CakePHP ログ出力
2CakePHP でログ出力させるメモです。
$this->log(ログに出力するメッセージ, ログ種別);
出力するメッセージは文字列でも配列でもかまいません。配列の場合は print_r されたものが出力されます。
ログの種別は LOG_DEBUG で debug.log 、 LOG_ERROR で error.log に出力されます。デフォルトは LOG_ERROR です。
ログファイルは LOGS で指定されたディレクトリへ出力されます。
デフォルトは /app/tmp/logs です。
ただこの定数 LOGS は cake/config/paths.php で指定されているので、app/config/core.php で定義されている定数のように気軽に変更しない方がいいかもしれません。
ログファイルが存在しない場合はファイルを作成してくれます。
出力されるログは下記のようになります。
2007-11-11 06:54:54 Error: メッセージ
LOG_DEBUG を指定するとログの “Error” の部分が “Debug” になります。
この log メソッドは Object クラスにあります。Object クラスは CakePHP の全てのクラスで継承されるクラスなので、コントローラ、モデル、ビューどこからでも $this->log() でログに出力させることができます。
CakePHP findBy での複数指定を調べたメモ
2先のエントリで書いた「CakePHP findBy で複数条件の指定で OR も指定可能」ですが、findByHogeAndFoo などの処理がどうなっているか気になったので調べたときのメモです。
- findByHogeAndFoo メソッドが実行されると model_php5.php ( Model クラス ) の __call メソッドが実行される
- __call メソッドでは DboSource クラスの query メソッドに findByHogeAndFoo のメソッド名と条件の値を渡す
- DboSource クラスの query メソッドでは、findBy または、findAllBy の後ろの文字列を取り出す
- 取り出した文字列を小文字に変換してさらに AND を _and_、OR を _or_ に変換する
- _or_ または _and_ で分割してフィールドを取り出す
- AND または OR にしたがって SQL の条件を組み立てる
というようなこと処理がされていました。
まとめると
- 複数指定はいくつでも可能
- AND または OR は混在して指定はできない
いくつでも指定はできるようですが、たくさんの条件をこれで指定するとソースの可読性が下がりそうですし、AND と OR が混在できないので普通はそんな指定はしないでしょう。
指定する場合は2つくらいにとどめておいて、それより多くなる場合は find の $conditions で指定した方が無難だと思います。
CakePHP findBy で複数条件の指定で OR も指定可能
2[cakephp]findByで複数条件の指定 | blog.hereticsintheworld
で紹介されていた
$this->Model->findByIdAndName( $id, $name )
が気になりソースを調べてみたところ OR も指定可能でした。
$this->Model->findByIdOrName( $id, $name )
ちなみに findAll でも同様に指定可能です。
CakePHP 管理画面を作成する方法
2CakePHP で管理画面を作成する方法です。
管理画面も CakePHP では簡単に作成することができます。
設定
/app/config/core.php の下記のコメントアウトをはずします。
define('CAKE_ADMIN', 'admin');
これで http://www.example.com/admin/controller/action という URL でアクセスできるようになります。
CAKE_ADMIN の値を変更すれば URL の /admin/ の値が変わります。
コントローラ
管理画面で使用するコントローラに管理画面用のアクションを追加します。
管理画面用のアクション名は admin_index のように admin_ が付きます。
この ‘admin’ の部分も CAKE_ADMIN によって変わります。
ビュー
管理画面用のアクションで表示するデフォルトのビューはアクション名と同じです。admin_index.thtml のように admin_ を付けます。
レイアウト
ユーザサイドの画面レイアウトと管理画面はレイアウトが違うことが多いかと思います。管理画面用のレイアウトを admin.thtml のように views/layouts/ に作成します。
管理画面へのアクセス時の共通処理
管理画面のアクセス時の共通処理として、アクセス制限をしたり、画面レイアウトの変更などがあります。
個別にアクションに追加してもいいのですが漏れなどがあるとまずいのでコントローラの beforeFilter メソッドを使用するといいかと思います。
管理画面で使用するコントローラ全てに共通して処理させるために、 /app/app_controller.php の beforeFilter に処理を追加します。
http://www.example.com/admin/contoller/action にアクセスすると
$this->params['admin'] = 'admin'
がセットされます。管理者用URL かどうかにはこれを使用します。また、’admin’ の値は CAKE_ADMIN で指定した値になります。たとえば CAKE_ADMIN を hoge にすると
$this->params['hoge'] = 'hoge'
になります。
if (defined('CAKE_ADMIN') && !empty($this->params[CAKE_ADMIN])) { // 管理者用のレイアウトを指定 $this->layout = "admin"; // 管理者用ログインチェックなどを行う }