2007-06-02 新ブログシステムへ移行
■ブログシステム移行
CakePHPで作ったブログシステムへの移行を進めています。
こちらのサイトも残しておきますが、今後は面倒ですが
http://life-hack.jp/labo/charly
までお越しください。
CakePHP関連で検索して下さる方が多いので、CakePHP関連のカテゴリも記載しておきます。
http://life-hack.jp/labo/charly/category/3
今後ともよろしくお願いします。
2007-05-21 Cake1.2 Behavior
■[CakePHP]CakePHP1.2のBehaviorを使う
CakePHPの1.2系から導入された(1.1系でもディレクトリだけは存在したw)「Behavior」、これでController→Component、View→Helper、Model→Behaviorという住み分けが完成したそうです。
そこでこのBehavior、何が出来るかというと他のComponentやHelperと同じようにMVC各クラスに共通機能を追加するためのモジュールとなっています。
CakePHP1.2ではデフォルトで/libs/model/behaviorsにacl.php、translate.php、tree.phpが入っていて、Modelクラスに追加できるようになっています。
ユーザが作成したBehaviorクラスは/app/model/behaviorに置くのですが、modelクラスでのBehaviorの利用法が他のControllerクラスやViewクラスと異なっていたため若干はまりました。。
ます、ComponentとHelperの使い方は以下の感じです
<?php class HogeController extends AppControlle{ var name = 'Hage'; var $components = array('Fuge'); //FugeComponentを利用 var $helpers = array('Hoge'); //HogeHelperを利用 ・・・ } ?>
となっています。なので慣れた人ならModelクラスでBehaviorを使うためにはこう書こうとするんじゃないでしょうか
<?php class HogeModel extends AppModel{ var $behaviors = array('Fuge'); //FugeBehaviorを利用・・・したい ・・・ } ?>
しかしFugeBehaviorがないと怒られてしまいます。。
- Controller→Components
- View→Helpers
- Model→Behaviors
と思うじゃないですか。
しかし正解は
<?php class HogeModel extends AppModel{ var $actsAs = array('Fuge'); //FugeBehaviorを利用 ・・・ } ?>
$actsAsなんですって。しかも自分の場合は$actsAsという存在をhttp://bakery.cakephp.org/articles/view/soft-delete-behaviorやCakeのコア部で発見していながら$actAsって書いてしまっていてさまよう始末・・・・・
まぁBehaviorは「ふるまい」を定義するので「Act」はまぁまぁ正しいんでしょうが、「Act」が複数形になって「actsAs」って書かないといけないとはやられました。。
2007-05-20 ScalixをCentOSにインストール(成功)
■[一般][メモ][オープンソース]ScalixをCentOS4.4にインストール(導入前解説)
大学院生になってさらに複数のメールアドレスを管理しないといけないようになり、しかも大学院でもらったメールアドレスにはスパムメールがてんこもり・・・(一般に公開されているので)ということで新しくメールクライアントを導入しようかと考えました。
メールクライアントといえばGmailやYahoo!などのWebmail系、Outlook ExpressやEdMax(私も使っています)などのインストール型がありますが、欲しい要件としては
- Webベース(バイト先、自宅、大学院等様々な場所でPCを扱うため一元で管理したい)
- 複数のメールアドレスを管理できる
- 無料(有料でもいいのがあったらいいのですが、有料→完璧にすばらしいもの→未だ発見できず なので無料なら自分で色々いじる意欲もでますんで)
- スパムメールを排除してくれる
- 自分で細部までカスタマイズ可能
くらいかと思いますが、WebベースのGmailやYahoo!ではカスタマイズがしにくいことやスパムフィルタリングが微妙そうという点、Gmailは個人情報を覗き見されている感がある点などからパス(あと、外部のアドレスを管理できますが微妙に使いづらいので)。Outlook ExpressやEdMaxなどのインストール型は様々な環境でメールを受信するので一元管理をしたいな・・・と。
そんなわけでたまたま発見したScalixに白羽の矢が立ちました。
しかしそれは同時に困難な道のりの始まりでした。。
まず、Scalixがどんなものかを簡単に説明しておきます。
- AjaxベースのWebメールシステム(Scalix Web Access)
- 拡張性が高い(高そう)
- 実はすごい歴史がありそう
- 前身となるのはヒューレットパッカード社のHP OpenMailだそうです。HP OpenMailは10万ものユーザが利用していたとScalixのHPに書いており、安心感があります。
- 携帯電話にも対応+セキュリティも充実
- オープンソース(無料)である
ちなみに、CentOSにインストールをした(現在日本語化までしておきました)感想として、Scalixのデメリットをあげておきます
- インストールが大変
- 実はデフォルトでは複数メールアドレスの管理に対応していなかった
- もしかしたらAjaxベースは微妙に使いにくい場合があるかも
- Ajax=Web2.0感は認めます(正しい定義ではないですが)。しかし今のクライアントPC環境においてはまだフルAjaxなWebメールクライアントは時期尚早だったのかもしれません。確かに使いやすいのは使いやすいのですが、インストール型PCと比べると微妙に・・・本当に微妙なのですがかゆいところに手が届かない感はありました。細かい点ですが、「受信ボックス」を右クリックしてもメニューが出てこないとか、一括で領域指定(一箇所をクリックしてからシフトを押しながら他の場所をクリックしたら領域指定できると思ったのですが)ができない場合が多いとか、Ajaxベースのシステムを作った経験もあるので技術的な難点が多い事は分かりますが、やや不満はありました。まぁしかしそこはScalixのバージョンが上がるたびに改善されていくと信じています。
とりあえず簡単なScalixの説明はこのくらいです。
Scalixのインストール編についてはまた近いうちに書いていきます。
2007-05-12 Tips
■[CakePHP]CakePHPで存在しないcontrollerが指定された際にデフォルトのcontrollerクラスを利用する方法
現在作成中のBlogシステム(http://life-hack.jp/labo/charly)はCakePHPで作られているのですが、HatenaDiaryの仕組みを元にしているため、最後の「charly」の部分はユーザーIDとなっています。
しかし、CakePHPは不便なことにルートディレクトリ(この場合は「http://life-hack.jp/labo/」)の次のディレクトリ(この場合は「charly」)をコントローラークラスの名称だと認識してCharlyControllerを探しに行きます。
当然CharlyControllerは見つからないため「Missing Controller」となるわけです。
Missing Controllerを対処するためには
- 指定のcontrollerクラスが存在する
- /app/config/routes.phpをいじって指定のcontrollerクラスに値を渡せるようにする
の2通りが考えられます。
今回の目標ははBlogControllerに引数として「charly」とそれ以降の引数を渡すことです。
この対処法として色々試してみました。
- /app/webroot/index.phpを改造+routes.phpにRouter::connect('/blog/*', array('controller' => 'blog', 'action' => 'index'));と記述
- /app/webroot/index.phpにてDispatcherクラスを作成しているため、Dispathcerクラスにわたる前にURLから「charly」にあたる部分を抽出する
- →うまくはいくのですが、URLがどうしても「http://life-hack.jp/labo/blog/」となってしまうので却下
- /cake/libs/router.phpを修正する
- /app/config/routes.phpをごりごり書く
まぁ色々試してはみたんですが、一番あっさりしてうまくいっているのは
Dispatcherクラス(/cake/dispatcher.php)の修正でした。
CakePHPのだいぶコアな部分なので修正が広範囲に広がってしまうのではないかとびくびくしていましたが、要は「Missing Controller」がでる際にデフォルトのcontrollerクラスをロードして指定してしまえばいいんだ・・・ということでした。
ってなわけでどんな修正をしたかというと・・・
<? //下準備(/app/config/bootstrap.phpに記載→bootstrapに定数を指定するべきかの議論はここでは割愛) define('DEFAULT_CONTROLLER','blog'); //デフォルトで使用するcontroller名 define('DEFAULT_CONTROLLER_ACTION','index'); //そのcontrollerで使用するaction名 ///cake/dispatcher.phpの91行目以降(Revision: 4758にて) if (empty($params['controller'])) { $missingController = true; } else { $ctrlName = Inflector::camelize($params['controller']); $ctrlClass = $ctrlName.'Controller'; if (!loadController($ctrlName)) { $pluginName = Inflector::camelize($params['action']); if (!loadPluginController(Inflector::underscore($ctrlName), $pluginName)) { if(preg_match('/([\\.]+)/', $ctrlName)) { Router::setRequestInfo(array($params, array('base' => $this->base, 'webroot' => $this->webroot))); return $this->cakeError('error404', array(array('url' => strtolower($ctrlName), 'message' => 'Was not found on this server', 'base' => $this->base))); //controllerクラスが見つからない場合 } elseif(!class_exists($ctrlClass)) { //変更ここから $ctrlName = Inflector::camelize(DEFAULT_CONTROLLER); //強引にデフォルトのcontrollerクラスをロード if(!loadController($ctrlName)){ $missingController = true; }else{ $ctrlClass = $ctrlName.'Controller'; //このままではパラメータが渡らないので新しいパラメータをURLから指定(若干の疑問あり) //ここを変更すれば、controllerクラスへ渡るパラメータを修正できる。 $newParams = split('/',$url); $params['pass'] = $newParams; $params['controller'] = DEFAULT_CONTROLLER; $params['action'] = DEFAULT_CONTROLLER_ACTION; } //変更ここまで //$missingController = true; //コメントアウト } else { $params['plugin'] = null; $this->plugin = null; } } else { $params['plugin'] = Inflector::underscore($ctrlName); } } else { $params['plugin'] = null; $this->plugin = null; } } ?>
しかしやはりCakeコア部分を修正するのには気が引けました。
現在はこれでうまくいっていますが、もしかすると将来的に機能追加などした際に変な歪が生じるかも知れません。
やはり一番スマートそうなのはroutes.phpの修正で、「指定したcontrollerクラス以外ならこのクラスを利用する」といった指定が簡単にできることでしょうか・・・。
なにかスマートな方法を知っている・思いついた方がおられましたら連絡いただければ幸いです。
■[CakePHP]データベース設定
SVNを使っていたりFTPで一括でアップロードする際にローカル環境とサーバー環境が違うためアップロードしたとたんにエラーになるのを防ぐ方法
まぁアップロードする際にdatabase.phpをフィルタリングする設定にすることでも事足りるんですが。
app/config/database.php <?php class DATABASE_CONFIG { var $default; function __construct() {//ローカル環境での設定 if(FULL_BASE_URL == 'http://localhost'){ $this->default = array('driver' => 'mysql', 'connect' => 'mysql_connect', 'host' => 'localhost', 'login' => '***', 'password' => '***', 'database' => '***', 'prefix' => '***'); } else {//サーバー上の設定 $this->default = array('driver' => 'mysql', 'connect' => 'mysql_connect', 'host' => 'localhost', 'login' => '***', 'password' => '***', 'database' => '***', 'prefix' => '***'); } } } ?>
どこかで同じ事をしていた人を見ましたが、メモってことで。
if(FULL_BASE_URL == 'http://localhost’)を用いることによって様々な場面でローカルならこう、サーバーならこうっていうロジックを作成できます。
ちなみに自分の場合はGoogle AdSenseをローカルでは非表示にして、サーバーでは表示するなどといった作りをしています(誤クリックで利用停止になりたくないんで・・・)。←IPやらではじくようにする方が絶対ですが、色んなPCを使ってアクセスするんで開発環境では・・・ってだけ分けてます。
2007-05-10 ちょっと便利なコード
■[PHP][CakePHP]置換について
<?php function str_replace_ex($replace,$text){ $out = str_replace(array_keys($replace), array_values($replace), $text); return $out; } echo str_replace_ex( array( 'search1' => 'replaced1', 'search2' => 'replaced2', ), 'search1とsearch2' ); //出力: replaced1とreplaced2 ?>
なるほどと思うTipsでした。 From CakePHP