2007年6月アーカイブ
これは何?
php フレームワーク CakePHP を smarty 対応したものです。
bake コマンドにより生成される html 及び、その書き出し元となる html テンプレートを smarty 化します。
もちろん、標準の bake コマンドや cake テンプレートとの併用も可能です。
更新履歴
- 20070702
- cake_smarty_0.1.2.11 template を調整
- 20070619
- cake_smarty 公開 (0.1.2.1)
cake bake の代わりに cake burn を使うことで smarty テンプレートを書き出すことができます。
ケーキ焦げてます。
動作環境
今のところ cake_1.2.0.5146alpha.tar.gz でしか確認していません。
しかも windows 環境下でしか確認してません。
別途、以下ライブラリを必要とします。
準備
- cake_1.2.0.5146alpha を用意
- 万が一、既存のプロジェクトに適用する場合は必ずバックアップを取っておいてくださいね。
- cake_smartyを download
- 2. を解凍したファイルを1. に上書きコピー
- vendor に smarty をコピー
- app/views にSmarty View class を「smarty_view.php」としてコピー
- app/app_controller.php の設定
- app/app_controller.php がない場合は cake/app_controller.php をコピー
- 以下のように記述
class AppController extends Controller {
var $view = 'SmartyAll';
}
使い方
- db の設定等、諸設定は終わってるものとします
- コマンドラインから cake/console/ へ移動
- cake bake の代わりに cake burn コマンドを使う
- cake burn から書き出される view は smarty テンプレートです。
元テンプレートが以下ディレクトリにあるので、自由にカスタマイズしてください
cake/console/libs/templates/views/smarty/
todo
smarty の array の扱い方が変。
$view->_array('key=>value')
もっとよいやり方がきっとある。何となくイメージもできてる
その他
php もまだまだ捨てたもんじゃないと思い始めました。
使用は自己責任でお願いします。
疑問・質問・フィードバック等お気軽にどぞ
「松本人志コンプレックス」とでもいうようなものがある。
それは、松本人志の作るものがおもしろくないわけがないから、
松本人志の笑いを理解するには高いコミュニケーション能力を必要とするから、
彼の笑いを理解できなかった時(おもしろくないと感じた時)、
それを自分のせいだと思ってしまう現象である。
で、何とかしておもしろさを見出そうとする。
例えばとかげのおっさんをカフカとか人間失格にダブらせてみたりとか。
大日本人はそんな「松本人志コンプレックス」から
解き放たれるための一作だ。
みなまでは言わない。
CakePHP 完全 smarty 化が完了しました。
ファイルまとめて使い方書けたら公開しようと思います。
需要の有無は関係ない!
CakePHP 完全 smarty 化の意義は
- bake による自動生成の元のテンプレートを smarty テンプレートとして切り出すことで、元ファイルに手を加えやすくなる
- その結果、bake コマンドに見切りを付けるタイミングを、後ろにずらせる。
- php コードと html の分離
- デザイナさんに与える脅威の減少
- 何より、読みやス
他にもいろいろあると思うけど、眠くて思い浮かばないです。
1.については以下を見比べていただければと。
まるまる貼っつけたので見辛いですが。
bake 元のテンプレート
index view について。
before
/cake/console/tasks/view.php 内
//-------------------------[INDEX]-------------------------//
$indexView = null;
$indexView .= "<div class=\"{$pluralName}\">\n";
$indexView .= "<h2>List " . $pluralHumanName . "</h2>\n\n";
$indexView .= "<table cellpadding=\"0\" cellspacing=\"0\">\n";
$indexView .= "\t<tr>\n";
foreach ($fieldNames as $fieldName) {
$indexView .= "\t\t<th><?php echo \$paginator->sort('{$fieldName['name']}');?></th>\n";
}
$indexView .= "\t\t<th>Actions</th>\n";
$indexView .= "\t</tr>\n";
$indexView .= "<?php foreach (\${$pluralName} as \${$singularName}): ?>\n";
$indexView .= "\t<tr>\n";
$count = 0;
foreach($fieldNames as $field => $value) {
if(isset($value['foreignKey'])) {
$otherModelName = $this->_modelName($value['model']);
$otherModelKey = Inflector::underscore($value['modelKey']);
$otherModelObj =& ClassRegistry::getObject($otherModelKey);
$otherControllerName = $this->_controllerName($value['modelKey']);
$otherControllerPath = $this->_controllerPath($otherControllerName);
if(is_object($otherModelObj)) {
$displayField = $otherModelObj->getDisplayField();
$indexView .= "\t\t<td><?php echo \$html->link(\$".$singularName."['{$otherModelName}']['{$displayField}'], array('controller'=> '{$otherControllerPath}', 'action'=>'view', \$".$singularName."['{$otherModelName}']['{$otherModelObj->primaryKey}'])); ?></td>\n";
} else {
$indexView .= "\t\t<td><?php echo \$".$singularName."['{$modelObj->name}']['{$field}']; ?></td>\n";
}
$count++;
} else {
$indexView .= "\t\t<td><?php echo \$".$singularName."['{$modelObj->name}']['{$field}']; ?></td>\n";
}
}
$indexView .= "\t\t<td class=\"actions\">\n";
$indexView .= "\t\t\t<?php echo \$html->link('View', array('action'=>'view', \$".$singularName."['{$modelObj->name}']['{$modelObj->primaryKey}'])); ?>\n";
$indexView .= "\t\t\t<?php echo \$html->link('Edit', array('action'=>'edit', \$".$singularName."['{$modelObj->name}']['{$modelObj->primaryKey}'])); ?>\n";
$indexView .= "\t\t\t<?php echo \$html->link('Delete', array('action'=>'delete', \$".$singularName."['{$modelObj->name}']['{$modelObj->primaryKey}']), null, 'Are you sure you want to delete #' . \$".$singularName."['{$modelObj->name}']['{$modelObj->primaryKey}']); ?>\n";
$indexView .= "\t\t</td>\n";
$indexView .= "\t</tr>\n";
$indexView .= "<?php endforeach; ?>\n";
$indexView .= "</table>\n\n";
$indexView .= "</div>\n";
$indexView .= "<div class=\"paging\">\n";
$indexView .= "<?php echo \$paginator->prev('<< previous', array(), null, array('class'=>'disabled'));?>\n";
$indexView .= "|\n";
$indexView .= "<?php echo \$paginator->next('next >>', array(), null, array('class'=>'disabled'));?>\n";
$indexView .= "</div>\n";
$indexView .= "<div class=\"actions\">\n";
$indexView .= "\t<ul>\n";
$indexView .= "\t\t<li><?php echo \$html->link('New {$singularHumanName}', array('action'=>'add')); ?></li>\n";
$indexView .= "\t</ul>\n";
$indexView .= "</div>";
after
/cake/console/libs/templates/views/smarty/index.tpl
<div class="{$pluralName}">
<h2>List {$pluralHumanName} </h2><table cellpadding="0" cellspacing="0">
<tr>
{foreach from=$fieldNames key="key" item=fieldName}
<th>{ldelim}$paginator->sort('{$fieldName.name}'){rdelim}</th>
{/foreach}
<th>Actions</th>
</tr>{ldelim}foreach from=${$pluralName} item="{$singularName}"{rdelim}
<tr>
{foreach from=$fieldNames key="field" item="value"}
{if $value.foreignKey}
{assign var="param" value=$this->_index1($value, $singularName)}
{if $this->call("is_object", $param.otherModelObj)}
{assign var="displayField" value=$param.otherModelObj->getDisplayField()}
<td>{ldelim}$html->link(${$singularName}.{$param.otherModelName}.{$displayField}, $view->_array('controller=>{$param.otherControllerPath}', 'action=>view', ${$singularName}.{$param.otherModelName}.{$param.otherModelObj->primaryKey}))}</td>
{else}
<td>{ldelim}${$singularName}.{$modelObj->name}.{$field}}</td>
{/if}{else}
<td>{ldelim}${$singularName}.{$modelObj->name}.{$field}{rdelim}</td>
{/if}
{/foreach}<td class="actions">
{ldelim}$html->link('View', $view->_array('action=>view', ${$singularName}.{$modelObj->name}.{$modelObj->primaryKey})){rdelim}
{ldelim}$html->link('Edit', $view->_array('action=>edit', ${$singularName}.{$modelObj->name}.{$modelObj->primaryKey})){rdelim}
{ldelim}$html->link('Delete', $view->_array('action=>delete', ${$singularName}.{$modelObj->name}.{$modelObj->primaryKey}), null, "Are you sure you want to delete #`${$singularName}.{$modelObj->name}.{$modelObj->primaryKey}`"){rdelim}
</td>
</tr>
{ldelim}/foreach{rdelim}</table>
</div>
<div class="paging">
{ldelim}$paginator->prev('<< previous', $view->_array(), null, $view->_array('class=>disabled')){rdelim}
|
{ldelim}$paginator->next('next >>', $view->_array(), null, $view->_array('class=>disabled')){rdelim}
</div>
<div class="actions">
<ul>
<li>{ldelim}$html->link('New {$singularHumanName}', $view->_array('action=>add')){rdelim}</li>
</ul>
</div>
bake で書き出される view ファイル
before
index.ctp
<div class="users">
<h2>List Users</h2><table cellpadding="0" cellspacing="0">
<tr>
<th><?php echo $paginator->sort('id');?></th>
<th><?php echo $paginator->sort('group_id');?></th>
<th><?php echo $paginator->sort('loginid');?></th>
<th><?php echo $paginator->sort('loginpass');?></th>
<th><?php echo $paginator->sort('name');?></th>
<th><?php echo $paginator->sort('comment');?></th>
<th>Actions</th>
</tr>
<?php foreach ($users as $user): ?>
<tr>
<td><?php echo $user['User']['id']; ?></td>
<td><?php echo $html->link($user['Group']['name'], array('controller'=> 'groups', 'action'=>'view', $user['Group']['id'])); ?></td>
<td><?php echo $user['User']['loginid']; ?></td>
<td><?php echo $user['User']['loginpass']; ?></td>
<td><?php echo $user['User']['name']; ?></td>
<td><?php echo $user['User']['comment']; ?></td>
<td class="actions">
<?php echo $html->link('View', array('action'=>'view', $user['User']['id'])); ?>
<?php echo $html->link('Edit', array('action'=>'edit', $user['User']['id'])); ?>
<?php echo $html->link('Delete', array('action'=>'delete', $user['User']['id']), null, 'Are you sure you want to delete #' . $user['User']['id']); ?>
</td>
</tr>
<?php endforeach; ?>
</table></div>
<div class="paging">
<?php echo $paginator->prev('<< previous', array(), null, array('class'=>'disabled'));?>
|
<?php echo $paginator->next('next >>', array(), null, array('class'=>'disabled'));?>
</div>
<div class="actions">
<ul>
<li><?php echo $html->link('New User', array('action'=>'add')); ?></li>
</ul>
</div>
after
<div class="users">
<h2>List Users </h2><table cellpadding="0" cellspacing="0">
<tr>
<th>{$paginator->sort('id')}</th>
<th>{$paginator->sort('group_id')}</th>
<th>{$paginator->sort('loginid')}</th>
<th>{$paginator->sort('loginpass')}</th>
<th>{$paginator->sort('name')}</th>
<th>{$paginator->sort('comment')}</th>
<th>Actions</th>
</tr>{foreach from=$users item="user"}
<tr>
<td>{$user.User.id}</td>
<td>{$html->link($user.Group.name, $view->_array('controller=>groups', 'action=>view', $user.Group.id))}</td>
<td>{$user.User.loginid}</td>
<td>{$user.User.loginpass}</td>
<td>{$user.User.name}</td>
<td>{$user.User.comment}</td>
<td class="actions">
{$html->link('View', $view->_array('action=>view', $user.User.id))}
{$html->link('Edit', $view->_array('action=>edit', $user.User.id))}
{$html->link('Delete', $view->_array('action=>delete', $user.User.id), null, "Are you sure you want to delete #`$user.User.id`")}
</td>
</tr>
{/foreach}</table>
</div>
<div class="paging">
{$paginator->prev('<< previous', $view->_array(), null, $view->_array('class=>disabled'))}
|
{$paginator->next('next >>', $view->_array(), null, $view->_array('class=>disabled'))}
</div>
<div class="actions">
<ul>
<li>{$html->link('New User', $view->_array('action=>add'))}</li>
</ul>
</div>
ね、ね、すっきりしたよね(自己暗示)。
・・・そろそろモヒカンでも生えてくるんだろうか。
結局諦めきれずに bake の smarty 化に取り組み始めたわけですが。
CakePHP は rails を手本に下だけあってなんつーかよくできてて、
bake に手を入れるのも元ファイルに手を加えずに
別のコマンド作るところまでは結構サクサク進めました。
で、スクリプト中に埋め込まれてる bake の元テンプレートを
smarty テンプレートとして切り出し始めたわけです。
(これがやりたかった)
で、smarty で配列をどうやって扱うかってのはこちらの方がサクッとクリアしてるので、
テンプレート変数のメソッドなら治外法権という性質を利用して、 SmartyViewにラッパーメソッドを追加。
function aa() {
$args = func_get_args();
return call_user_func_array('aa', $args);
}
SmartyViewのインスタンスは$viewとしてテンプレート内から参照できるので、
Title: {$html->input('Post/title', $view->aa('size', 40, 'class', 'classname'))}
と書くことができる。邪道な気もしますが。
memo-space :: CakePHP日記:Smaryテンプレート内での配列生成
楽勝かと思いきや、html ヘルパーのlink で上手くいかないんですよ
/**
* ↓本来この形が想定されてるので、パラメタが渡せない
* array('action'=>'edit', 2)
*/
$html->link('Edit', $view->aa('action', 'edit', 2))
で、SmartyView のメソッドをこんなんにしました。
function _array() {
$args = func_get_args();
$array = array();
foreach ($args as $key=>$var) {
if (ereg("=>", $var)) {
$keys = split("=>", $var);
$array[$keys[0]] = $keys[1];
} else {
$array[$key] = $var;
}
}
return $array;
}
で、こう使う
/**
* 'action=>edit' であって、'action'=>'edit'ではない
*/
$html->link('Edit', $view->_array('action=>edit', 2))
せっかくのスマートなソースをぐだぐだに書き換えつつ
どんどん道を外れていく気がする。
とのたまったこの方の懸念のさらに斜め下を進んでる気がする。
それは、bake が生成する html を気軽に変更したいからです。
最終的にはこれが一番の理由です。
ウノウラボの id: komagata さんの記事が
何となく気になったので書いてみる。
別に間違っててもクビになるわけじゃないし。
MySQLユーザー的には常識なのかもしれませんがMySQL 5.0からはインデックス結合という機能があるそうです。1テーブル1インデックス問題(勝手にそう呼んでいる)が解決するかもしれないと思って調べてみました。
ウノウラボ Unoh Labs: MySQL5からのインデックス結合で1テーブル複数インデックスを使う
はい、知りませんでした。複数インデックス。
CREATE TABLE `employees` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(32) default NULL,
`age` int(11) default NULL,
PRIMARY KEY (`id`),
KEY `index_name` (`name`),
KEY `index_age` (`age`)
)
でも、上の構造で、name, age を元に抽出するつもりだとすると、
自分の感覚では複合インデックス付ける。
CREATE TABLE `employees` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(32) default NULL,
`age` int(11) default NULL,
PRIMARY KEY (`id`),
KEY `index_name_age` (`name`, `age`)
)
で、1テーブル1インデックスなので、
どのクエリも取りこぼさないような組み合わせの
複合インデックスを複数作ってた。
別にこれでもいんじゃないかと思うんだけど、
複数インデックス使ったらクエリに応じた
複合インデックス作りまくる手間が省けるって事かな。
何も考えずに、インデックスかけたいフィールドに
インデックスつけりゃいいのかな。
結論として、DBに関しては耳を塞いでる自分がいる。
じゃなくて、とにかく MySQL5 を使えってことだと思った。
サーバ間でのファイルの同期に lftp 使ってるが、mirror -Re の時、
1階層目のディレクトリにはちゃんと -e オプションが効くが
2階層目以下で無視されてるくさい。
なんだこりゃ
追記
mirror -R -e --delete-first /local/dir /remote/dir
↑で上記現象が出てたけど、 --delete-first オプション削ったら上手くいった。
マニュアルによると、
- delete-first delete old files before transferring new ones
うーむ。。関係なさそうな。。
そもそもわざわざこのオプションつけたのは、これ付けないと
変更したファイルが上書きされなかったからだったような。
昨日満員電車の中で携帯でブラインドタッチでメール打ってる女の人がいた。
真後ろに立ってたら、その女性は顎の下に携帯を当て、
画面を見ずに手を動かしてたので、気になって画面を覗き込むと(ごめんなさい)、
「この度アルバイトを辞めさせていただきたく」
っていう文面ができあがりつつあった。
- それはメールでいいのか?
- 電車降りてからでもいんじゃないのか?
- そもそも、画面見たらいんじゃないのか?(携帯を顎の下に構えたところで大した省スペース化にはなってないし、そこまでスシ詰めでもなかったし)
いろいろ突込みどころがあるとは思ったけど、
そんなメールの文面も見たくないくらい、そのアルバイトが嫌だったんだろうか。
なんにせよ、携帯でブラインドタッチを試みるっていう発想はなかったわ
CakePHP smarty 化の障壁は、bake コマンドからの view 生成である。
bake コマンドから view を smarty テンプレートで書き出せたら
html 中に 今更 php タグを埋め込む後ろめたさから開放されそうだ。
で、ソース読んでみたら、html コードべた書きしてた。
断念。
テンプレート使えばいいのに。
開発めんどくさいでしょうよ。
↓延々こんなの
/cake/console/libs/tasks/view.php
//-------------------------[INDEX]-------------------------//
$indexView = null;
$indexView .= "<div class=\"{$pluralName}\">\n";
$indexView .= "<h2>List " . $pluralHumanName . "</h2>\n\n";
$indexView .= "<table cellpadding=\"0\" cellspacing=\"0\">\n";
$indexView .= "\t<tr>\n";
foreach ($fieldNames as $fieldName) {
$indexView .= "\t\t<th><?php echo \$paginator->sort('{$fieldName['name']}');?></th>\n";
}
最近はてダかいてたら 100% firefox 落ちます。オレだけ?
うざ杉。
習作に、CakePHP の helper を作ってみました。
以下のような設定ファイルを読み込んで、リンク付きのメニューを出力します。
[config]
admin = false[group1]
group1.index = "index"
group1.add = "add"[グループ2]
group2.index = "なんかのアクション"
group2.add = "テスト"
記述ルールは、
[グループ名]
{controller 名}.{action 名}
- [config]は予約語で、「admin=true」の時、リンクの頭に強制的に 「admin/」をつけます。
デモ
http://pm11op.xii.jp/pm11op/cake/public_html/hello
↓イメージ画像
動作環境
- cake_1.2.0.5146alpha
- php4
で動作確認しました。1.1 系では動かなかったです。
download
http://pm11op.xii.jp/pm11op/cake/menu.tar.gz
使い方
- 以下を同梱してます。 app ごとまるっとコピーするなり、個別に当該箇所にコピーするなりしてください。
- /app/webroot/css/cake.menu.css
- /app/views/helpers
- /app/views/helpers/menu.php
- /app/config/menu.ini
- controller 内で Menu helper を使えるように
例えば全ての controller で使う場合は cake/app_controller.php を app/ にコピーして、以下のようにすればよいと思います。
class AppController extends Controller {
var $helpers = array( 'Menu');
}
- view に以下記述
<?php $menu->display();?>
WEBアプリの管理画面とかに便利だと思って作りました。
じゃ。
思ってたら、開発用の db にテストデータ大量挿入でたまげた。
で、ドキュメント読んだら、書いてあった。
database.php file の中には、$test 接続設定も含まれています。ここに設定を記入(または同じフォーマットで設定を追加)し、アプリケーションの model 内で
var $useDbConfig = 'test';
のように設定して利用してください。この方法で、任意の接続設定を追加できます。
4章 設定
この辺は rails のようにはいかないのねー。
てことで、できるようにしてみた。自己責任でしてみた。
まず、モデル、コントローラの雛形は
cake/app_model.php, cake/app_controller.php ですが、
これを app/ にコピーすると、そっちを使ってくれます。
これを利用して、test.php から呼び出された時は
test 用の db を使用するように変更。
- cake/app_model.php を app/ にコピー
- app/app_model.php の内容を以下のように変更
class AppModel extends Model{
function __construct($id = false, $table = null, $ds = null) {
if (defined('CAKE_TEST_OUTPUT_HTML')) {
$this->useDbConfig = 'test';
}
parent::__construct($id, $table, $ds);
}
}
わざわざコンストラクタ作ってるのはそうしなきゃ分岐できないのですよ。
CAKE_TEST_OUTPUT_HTML は test.php でしか宣言されてないので、勝手にフラグとして使用。
これで安心して testcase の中から
$this->ObjectTest->save($data);
とかできます。
(追記)
↓ここに同じようなこと書いてありました。
http://www.1x1.jp/blog/2006/09/cakephp_db_config.html
__construct をつかうべきですね。ソース修正しました。
デザインも変えてみた。ブログのデザインって別になんでもいいよね。
どうせ reader で読むし。
知らん間に smarty 依存症になっていたようだ。
CakePHP 使ってて何がうざいってテンプレートエンジン使ってないことだ。
helper があってタグとか form 要素とか楽に作れるようにはなってはいるが。
そこまで rails を再現しなくてもよいのではないか。
ドキュメントに 「cache 機能もあるし、smarty 使わなくても充分に高速」
的なこと書いてあったけどそういうことじゃなくて、
<?=$hoge;?>
-------------
{$hoge}
字数でいったら4文字なんだけど、打ちにくいのよ。
あと、デザイナーさんに与える威圧感も全然違う。
かといって、bake は捨てがたいし、管理画面は bake で生成、
表の view は smarty とか使い分けるのがよさそうとだ思った。
今後やりたいこと調べるべきことをメモ
- group 認証つけたい
- layout に admin 用を追加したい
- menu controller みたいの作って、自動化したい(controller, action を網羅)
- smarty 使いたい
この方の blog 役に立ちまくりでした。
なんで seesaa? って思ったけど。そこがまたステキ。
あと、 bake コマンドに見切りを付けるタイミングがわからんです。
みんなどうしてんだろう。
を見たらrails のそれとほっとんど一緒だった。こりゃあいい。
で、ドキュメントを読み始めたら30分で寝てしまった。 in 会社
ドキュメントはね、寝る前に読むもん。
例えば電車の中とか。
あとこれだけのエントリ書くのに firefox が5回落ちた。
最近の php 嫌いから来る 俺 php 鎖国状態がさらに php 嫌いを
加速してると思ったので、フレームワークを変えてみることにしました。
フレームワークありすぎるので、
ポインツを以下に絞った結果、
- php4 系
- ソースコード小さめ
- rails ベース
CakePHP にしましたよ。
因みに今まで使ってたのは Mojavi2系。ロートルです。
最近の MT は動的ページを php で作ってるらしい。
てことでソース読んでたら、 /mt/php/mt.php にて
軟弱 Singleton(?) パターンを発見した。
class MT {/***
* Constructor for MT class. Also declares a global variable
* '$mt' and assigns itself to that. There can only be one
* instance of this class.
*/
function MT($blog_id = null, $cfg_file = null) {
error_reporting(E_ALL ^ E_NOTICE);
global $mt;
if (isset($mt)) {
die("Only one instance of the MT class can be created.");
}
$this->id = md5(uniqid('MT',true));
$this->init($blog_id, $cfg_file);
}..略..
}
スクリプト内で横断的に使われるのであろう MT クラスは
常に同じ ID とか設定とか持ってなきゃいけないとかそういうことなんだろうと思う。
なんか uniqid とかしてるし。
で、インスタンスは 「$mt」 って変数名で作れってコメントに書いてある。
で、「$mt」 は global になってて、
既に「$mt」が存在したら、「Only one instance of the MT class can be created.」
って怒られて、処理終了。
ちゃんと Singleton にすればいいのに。
コメントも、そんな三行も書かなくても Singleton とだけ書けば事足りるし。
それに、これ使った瞬間に、以降スクリプト内で「$mt」って変数を使った時点で
挙動が怪しくなる地雷含みでもあるわけで。
てことで勝手にリファクタリング。
class MT {/***
* @singleton
*/
function MT($blog_id = null, $cfg_file = null, $factory=true) {
error_reporting(E_ALL ^ E_NOTICE);
if ($factory) {
$this = MT::getInstance($blog_id, $cfg_file);
}
}
function &getInstance($blog_id = null, $cfg_file = null) {
static $instance;
if ($instance === NULL) {
$instance = new MT($blog_id, $cfg_file, false);
$instance->id = md5(uniqid('MT',true));
$instance->init($blog_id, $cfg_file);
}
return $instance;
}
..略..
}
new でインスタンス作っても、第3引数をわざわざ false に指定しない限り、
常に同一のインスタンスを返してくれます。
なんでこんな変なことやってるかっていうと、
これが添削じゃなくてリファクタリングだからです。
動いてるものはそのまま動くように。
・・・多分動く。テスト書いたわけじゃないし、知らん。
php で Singleton は↓この辺とか、
Pear のライブラリソースコード眺めてたらちょいちょい出てきます。
http://www.doyouphp.jp/sample/sample_class_dp_singleton.shtml
人のソースは読んだ方がよいですね。めんどくさいけど。
