movabletypeの最近のブログ記事



最近の 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



人のソースは読んだ方がよいですね。めんどくさいけど。