2007年7月アーカイブ



会社に水筒持ってく時点でどうよって話はさておき、


おいしいよね、カルピス。




PHP 4 のサポートが年内で終了するとかで。


今のところそんなに思い当たる節が無いので


(いよいよ切羽詰ってからでも間に合うかな?くらいの心当たり)


愕然とするわけではないが、やはりめんどくさい話なわけで。



「われわれの見たところでは、積極的に開発を行っている人はみなすでに移行を済ませている。統計データの数値は、PHP 4ベースのレガシーアプリケーションがたくさんあるために歪められてしまっている。そういったアプリケーションは現状のまま稼働しているので、誰も変更したがらないからだ」とGutman氏は主張する。「PHP 4」のサポートが2007年末で終了へ


この言い分って、随分暴力的じゃないか。


「統計データの数値は、PHP 4ベースのレガシーアプリケーションがたくさんある」ことを証明しているんじゃないのか。数値を歪めてるってなんだよ、それw


しかも「誰も変更したがらない」ってわかってるやん。



  • 動いてるスクリプトはさわりたくないのが世の常

    • リファクタリングとかいうけど、昔のスクリプトって、本当そんなレベルじゃないのよ。いわゆる php の悪いところ。



  • で、その動いたスクリプトを書いた人は往々にして多忙

    • 余裕のある人間は、そんなリスクを負うつもりのない人間

    • こういうやつは大抵「自分の」書いたプログラムは php4 でも php5 でも動きますとか、人の書いたプログラムは関係無いですとか言い切る



  • 予算が発生しない作業なのがそもそも問題

  • php4 と php5 を同じサーバ上で共存させるのが面倒(切り替えるのは簡単)な以上、 php4 と php5 で動作するスクリプトを書くのは困難

  • そもそも pear って php4 向きでしょ。pear な部分を作り変えるのは、さすがにちょっと。。。


まあそんなこんなで、php5 への移行はやっぱり進んでないと思う。


でも、何とかしなきゃならん状況なんでしょう。



じゃあ、どうするかって話だけど、


いよいよ困ってるような所は、クライアントにリニューアルでも持ちかけりゃいいんじゃね?


予算が発生すれば、それなりに動く人は動くわけで。



php5 に作り変えなきゃいけないわけですが、


単に作り変えても意味無いので、どうせだったらリニュりましょかとか


言えばいんじゃない?(人ごと)



僕はなるべく意識しながら、CakePHP 使ってこうと思います。


実際問題してないけどね、意識。



↓意識するなら、これです。エライ!


http://www.1x1.jp/blog/2007/06/php_php4_to_php5.html




前回ひどい目にあったサンダル履くために


親指と人差し指の間にばんそうこうを貼った。



さらになるべくそこに力がかからないように


親指だけに鼻緒を引っ掛けるようにして足を持ち上げ、


かかとから着地するとサンダルずれしないことに気づいた。



結果、サンダルずれはしなかったが、ものすごく疲れたし、


歩くたびにペタペタ音がした。


タラちゃんか。俺は、タラちゃんか。



デキの悪い道具を上手く使うための努力っていうのは


この世から無くなるべきだと思った。



何かを作ろうという人はすべからくこの気持ちを持つべきなんじゃないか。



イチかバチか「すべからく」って言葉を使ってみた。




なんかはてダに変なの付いたと思って見てたらこういうことか。


http://d.hatena.ne.jp/hatenadiary/20070711/1184149817


これが、はてなのネガティブブックマーク(ネガブ)に対する対策ってことだろう。



はてブに規制をかけるのではなく、


システム上プラスにしか働かないシステムで相殺しようっていう発想は好きだ。


なんか人気ないみたいだけど。



自分で間違ってつけたスターが消せないらしいけど、


システムの性質上、別にそれでよいんじゃないか。


間違うのは最初の数回くらいだろうし、


そのための追加コードは無意味だと思う。



僕は別に無くても困らないし、


そもそもこの追加機能自体、使うことも無いかもしれん。


CakePHP

| | コメント(0) | トラックバック(0)



plugin の存在を完全にスルーしてた。


CakePHP | 13章 プラグイン


汎用的な controller は plugin として作るべきなのか。


しまった。component として作ってた。




CakePHP 1.2.0.5427alpha がリリースされました。


まだ alpha。



console 周りが結構変更されてます。


bake コマンドの元ファイルが template になったみたいですね。


妥当な流れだと思います。



とはいえ。


そのテンプレートの中身はこんなんなんですよ。


/cake/console/libs/templates/views/view.ctp より一部抜粋。



$i = 0;
foreach ($fields as $field) {
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}

if (in_array($field['name'], array_keys($foreignKeys))) {
$otherModelClass = $foreignKeys[$field['name']][1];
$otherModelKey = Inflector::underscore($otherModelClass);
$otherControllerName = Inflector::pluralize($otherModelClass);
$otherControllerPath = Inflector::underscore($otherControllerName);
if (isset($foreignKeys[$field['name']][2])) {
$otherModelClass = $foreignKeys[$field['name']][2];
}
$otherSingularVar = Inflector::variable($otherModelClass);
$otherModelObj =& ClassRegistry::getObject($otherModelKey);
$otherPrimaryKey = $otherModelObj->primaryKey;
$otherDisplayField = $otherModelObj->displayField;
echo "\t\t<dt{$class}>".Inflector::humanize($otherModelClass)."</dt>\n";
echo "\t\t<dd{$class}>\n\t\t\t<?php echo \$html->link(\${$singularVar}['{$otherModelClass}']['{$otherDisplayField}'], array('controller'=> '{$otherControllerPath}', 'action'=>'view', \${$singularVar}['{$otherModelClass}']['{$otherPrimaryKey}'])); ?>\n\t\t\t&#160;\n\t\t</dd>\n";
} else {
echo "\t\t<dt{$class}>".Inflector::humanize($field['name'])."</dt>\n";
echo "\t\t<dd{$class}>\n\t\t\t<?php echo \${$singularVar}['{$modelClass}']['{$field['name']}']?>\n\t\t\t&#160;\n\t\t</dd>\n";
}
}
?>
</dl>
</div>


だめだ、やっぱりなじめない。。。



cake_smarty の対応はどうしよっかな。


今回はスルーして、ベータ版出てからにしよっかな。




最初は感動するものの、使えば使うほど嫌いになっていく HTML_QuickForm がメンテナンス終了したとか何だとか。



とうとうHTML_QuickFormのメンテナンスが終了してしまった(正確に言うと追加開発が終わっただけでバグフィックスは継続しておこなわれる模様)。



PHPのテクメモ | HTML_QuickForm suspended



僕にとって、「昔の彼女が結婚しました」みたいな話だ。


あの時はありがとう、どうぞお幸せに。



みんな CakePHP に乗り換えればよいと思う。


こっちのがきっと幸せになれる。




買ったばかりのサンダル履いて会社行ったらおもっきり靴ずれした。


親指と人差し指の間の鼻緒的なものが当たる個所がベローンってなった。



まあ、試着した時からその予感はあったんだけど。



サンダルずれしないように、鼻緒の部分をやさしくコーティング


してくれるような商品はこの世にないもんだろうか。



あるとすれば、商品名は「サンダルズレナーイ」以外に考えられなかったので、


それで検索してみたら、ヒットしなかった。



誰か作ったらよいのにと思う。


でも、誰か作っても、商品名が「サンダルズレナーイ」じゃなかったら


潜在顧客を逃すことになるので注意すること。



追記

「サンダルズレテナーイ」でも可。




PHPでクロージャ


作ってみたものの、実はあんまり用途が思い浮かんでない。


なんとなく、 array_walk がキーワードに浮かんでは来るけど。



てことで、とりあえず smarty で使ってみようと思う。



CakePHP を完全 smarty 化してみたものの、


smarty 内での配列の扱いが微妙だ。


↓事の顛末はこの辺に。


http://d.hatena.ne.jp/am11op/20070614/1181837256


要は、php ならこう書くべきところを



<?php echo $html->link('Edit', array('action'=>'edit', 2));?>

smarty では view に変なメソッド作った上でこう書く必要があった。



{$html->link('Edit', $view->_array('action=>edit', 2))}

まあ、これでもよいんだけど、せっかくなんで closure (的なもの)を使ってみる。


Closure はこんなの。



class Closure {
var $_args;
var $_func;
/**
* @private
*/
function Closure($func=null, $args=null) {
if ($func) {
$this->_args = $args;
$func = ereg_replace("^function\([^\)]*\) *\{", "", $func);
$func = ereg_replace("\}$", "", $func);
$this->_func = $func;
}
}

/**
* @param $func string closure
* @param $arg1 $mixed first object/var which is used in $func
* @param $arg2 $mixed second object/var which is used in $func
* ...
*/
function bind() {
$args = func_get_args();
return new Closure(array_shift($args), $args);
}

/**
* use this method to call closure
*/
function call() {
$func = create_function('$args', $this->_func);
return $func($this->_args);
}

function func() {
$args = func_get_args();
$obj = new Closure(array_shift($args), $args);
return $obj->call();
}
}


無駄にインスタンス量産してるのは、書き直すのが面倒だったから。


このクラスを closure という名前で assign_by_ref してやって、


smarty 内からこう使う。



{*$html->link('Edit', $view->_array('action=>edit', 2))*}
{$html->link('Edit', $closure->func("return array('action'=>'edit', 2);"))}

文字数増えてる!


ネタです!


まあ、ちょっと変数を php で処理して何かのメソッドに渡したい時、


一回しか使わないような modifier をいちいち作らなくてよいので便利かも。


ただし、入力値に対して使う場合は任意のコードを実行されないように気をつけること(棒読み)。




cake1.2の話


CakePHP では view で エラーメッセージを指定することで


任意のエラーメッセージを出力できます。



{$form->error('name', 'ちょwww名前wwwww')}

rule が一つの場合ならこれでも問題ないのですが、


メールアドレスの validation など、


入力が無い場合と入力値が不適切な場合で


違うエラーメッセージを表示したい場合には


view だけでは実現できません。



そんな時には


model の $validate を以下のように指定すれば OK です。



class User extends AppModel {

var $name = 'User';
var $validate = array(
'name' => array(
'rule'=>VALID_NOT_EMPTY,
'message'=>'名前を入力してください'
),
'email' => array(
array(
'rule'=>VALID_EMAIL,
'message'=>'メールアドレスが不適切です。'
),
array(
'rule'=>VALID_NOT_EMPTY,
'message'=>'メールアドレスを入力してください'
),
),
'comment' => array(
'rule'=>VALID_NOT_EMPTY,
'message'=>'コメントを入力してください'
),
);

}

manual には書いてないけど、ソースには書いてありました。


よくありますね、こういうこと。




http://d.hatena.ne.jp/am11op/20070702/1183376369


↑前エントリのクロージャもどきがものすごく使いたくならない理由がわかった。



function closure($str) {
	$str = ereg_replace("^function\(\) *\{", "", $str);
	$str = ereg_replace("\}$", "", $str);


$func =create_function('', $str);
$func();
}

class Test{
function sayTest(){
echo 'test';
}
}
$obj = new Test;

function piyo($bool, $obj='') {
if ($bool) {
closure($obj['onSuccess']);
} else {
closure($obj['onFailure']);
}
}

$arr1 = array(
'onSuccess'=>'echo "OK!";',
'onFailure'=>'echo "NG!";',
);

echo piyo(true, $arr1); // OK!
echo piyo(false, $arr1); // NG!

$arr2 = array(
'onSuccess'=>'function(){echo $obj->sayTest();}', // この時点で syntax error
);

echo piyo(true, $arr2);

class とか instance 使った時点で閉じた空間じゃなくなるので、


こういうものはいくらそれっぽく作っても、


結局 closure とは呼べないだろうと思った。



結論

失敗例を増やしただけ




※これ失敗でした。↓にもちょっとマシなやつ書いてます


http://d.hatena.ne.jp/am11op/20070702/1183392610


CakePHP 使ってたら、ものすごく closure 使いたくなった。


ググったら途中までやってる方達がいたので、


それパクって作ってみた。



↓途中までやってる方達


http://blog.xole.net/article.php?id=419


http://p0t.jp/mt/archives/2007/04/1byte.html


要は create_function を使えばよいわけだ。


closure.php



function closure($str) {
$str = ereg_replace("^function\(\) *\{", "", $str);
$str = ereg_replace("\}$", "", $str);


$func =create_function('', $str);
$func();
}

function hoge($str, $func='') {
echo $str;
if ($func) {
closure($func);
}
}

echo hoge('こんにちわ。', "function() {echo 'クロージャだよ!';}");


実行結果



こんにちわ。クロージャだよ!


ものすごく使う気にならないのはなんでだ。




http://d.hatena.ne.jp/am11op/20070702/1183376369


↑前エントリがただの劣化コピーだってことに電車の中で気が付いた。


てことで、勝手にリベンジ。



その前に、closure の定義自体はとりあえず置いておいて、


自分が作ろうとしてる(欲しい)のは何なのか。



  • 外側の変数を参照できる

  • 使うその場で定義できる



↓ていうか、これ。


http://itpro.nikkeibp.co.jp/article/COLUMN/20050930/221971/?ST=oss



これができないのは、ただの callback 関数なんじゃないかと思うわけです。



で作ったのがこれ。



/*
* closure を実現するための class
*/
class Closure {
var $_args;
var $_func;
/**
* @private
*/
function Closure($func, $args) {
$this->_args = $args;
$func = ereg_replace("^function\([^\)]*\) *\{", "", $func);
$func = ereg_replace("\}$", "", $func);
$this->_func = $func;
}

/**
* @param $func string closure
* @param $arg1 $mixed first object/var which is used in $func
* @param $arg2 $mixed second object/var which is used in $func
* ...
*/
function bind() {
$args = func_get_args();
return new Closure(array_shift($args), $args);
}

/**
* use this method to call closure
*/
function call() {
$func = create_function('$args', $this->_func);
$func($this->_args);
}


}

// 以下、使用例
class Test{
function sayTest($int=0){
return 'this is a test.';
}
}
$obj = new Test;

function piyo($bool, $obj) {
if ($bool) {
$obj['onSuccess']->call();
} else {
$obj['onFailure']->call();
}
}

$hoge = "you know, ";

$arr = array(
'onSuccess'=>Closure::bind("function(\$args){echo '$hoge'.\$args[0]->sayTest();}", &$obj),
'onFailure'=>Closure::bind("function(\$args){echo 'fail!';"),
);

echo piyo(true, $arr); // you know, this is a test.
echo piyo(false, $arr); // fail!



  • Closure::bind の第一引数に closure を渡す

    • closure 内の instance は全て $args とする



  • $args に対応する instance を第二引数以降に渡す

  • closure はダブルクォーテーションでくくる場合は、$args の前に「\」を付ける必要がある

  • closure の頭に「function(\$args){」、尻に「}」が付いているが、これは closure であることを明示するためである

    • どっちみち ereg_replace で削除されるので、はっきり言って必要ない





「\」がウザい場合は、クロージャをシングルクォーテーションで囲って、


普通の変数も引数に渡してクロージャ内から $args[n] として参照すればよいです。



ちょっとは closure ぽくなったでしょか。