Home

12

日記
息継ぎEdit

大量のドキュメントとか原稿とかを書き終わるまで、そっちに集中するための他のことはしないようにしようと思っていたら、いつまで経っても終わりゃーしねーでやんの。潜り続けるのに飽きたんで息継ぎ1回。本当は連休中にいろいろやっておくつもりだったんだけど、やっぱり(子供がいる)家では仕事できんなー。

Published At2006-05-10 00:00Updated At2006-05-10 00:00

日記
やっと終わったEdit

っつーか、ひとまず提出しただけなんだけど、もう長いことずっとかかっていたドキュメント+原稿どっちもいったん手を離れてくれて、ごっつい気が楽になった。久しぶりに趣味のコードでも書くか。

Published At2006-05-16 00:00Updated At2006-05-16 00:00

日記
腰が痛いEdit

今日、明日は、サーバー10台くらい+フルラック2個付きの引っ越し作業。まだ半分くらいしか終わってないのに、マジで腰が痛い。明日残り半分できるんだろうか。っつーか今日の帰りの電車で立ってられないかも。

Published At2006-05-19 00:00Updated At2006-05-19 00:00

日記
やばいよやばいよEdit

一晩寝ても腰の痛みが全然ひいてないよ。

Published At2006-05-20 00:00Updated At2006-05-20 00:00

日記
CSSのレイアウトEdit

今後標準的に使っていくものを決める際に、独自のレイアウトCSSを作るか、それともどこか有名どころの(ライセンス的に自由な)CSSを採用するか、検討中。

試しにYUIのgridを使ってみたんだけど、これってYUIライブラリの中でも整合性取れてなくね? っつーか、最初に試したのがgridでレイアウトした中に、カレンダーを表示するという組み合わせで、早速破綻が生じた(カレンダーのタイトル部分がずれる)んで、それ以上試す気力を失ってしまった。

reset.cssでcaption,th {text-align:left;}しているのが原因だということは分かったから、場当たり的に直す(calendar.cssでcaption,th{text-align: center;}するとか)のは簡単なんだけど、そういうことをやらなきゃいけないんだったら、初めから全部自分で把握できるCSSレイアウトを採用した方がましな気もしちゃうんだよなー。

Published At2006-05-22 00:00Updated At2006-05-22 00:00

日記
Zend_Db_Tableの使い勝手の向上Edit

Zend_Db_Tableの使い勝手が良くないんで、独自にjoin対応してみたりもしたんだけど、やっぱりああやって元クラス自体に手を入れなきゃならないアプローチは実用レベルにはなり得ないよなーということで、別アプローチでZend_Db_Table周りを使いやすくしてみた。

ソースを見れば分かるけど、要はZend_Db_Table、Zend_Db_Table_Row、Zend_Db_Table_Rowsetのインスタンスをコンポジットに持つ集約クラスを作って、状況に応じて妥当な内部クラスのメソッドを呼ぶ、というのが基本的な構造。

で、それに加えて、Zend_Db_Tableでは扱えない複数テーブルにまたがったデータのハンドリングを行いやすくするための、拡張カラムの呼び出し機能を追加してある。

Zend_Db_Tableで処理を書こうとすると、

class Foo extends Zend_Db_Table{}
$table = new Foo();
$rowset = $table->fetchAll();
foreach ($rowset as $row) {
echo $row->id;
}
$row = $table->find(1);
echo $row->id;

みたいな感じで、Table、Row、Rowsetオブジェクトがいちいち発生してうざかった。それを、

class Foo extends Zend_Db_Table{}
$table = new WEBXP_Db_Object(new Foo());
$table->fetchAll();
foreach ($table as $row) {
echo $row->id;
}
$table->find(1);
echo $table->id;

みたいな感じで、一つのオブジェクトで完結して処理が書けるようになる。

あと、fooテーブルがbar_idカラムでbarテーブルとリンクするような構造だった場合、

$table->fetchAll();
foreach ($table as $row) {
$bar = $row->bar; // $row->barIdから自動的にbarテーブルオブジェクトを取得
}

といった感じで、規約通りのテーブル構成だった場合は、プロパティ名から自動的にリンクするテーブルのオブジェクトを取得してくれる。

あと、拡張カラム名とその内容を取得するためのselect文を定義しておけば、規約外の構造でリンクされる他テーブルの情報を、プロパティとして取得できるような機能を追加してある。

といったあたりまで拡張したら、Zend_Db_Tableもずいぶん使い物になるんじゃなかろうか。今後互換性のない機能拡張がないことを祈りつつ、このアプローチをしばらく試してみよう。

Published At2006-05-22 00:00Updated At2006-05-22 00:00

日記
pdo-mysqlのbindの挙動の違いEdit

Windows/PHP 5.1.4/MySQL 4.1.7(※$dbはpdoMysqlを使ったZend_Db_Adapterだけど、内部の処理はほぼそのままPDOを叩いているだけ)では、

$sql = 'select id from bar where foo_id = :id';
$result = $db->query($sql, array('id' => 1, 'test' => 'test'));

みたいなコードが動くのに、Fedora Core3/PHP5.1.4/MySQL 4.1.19では、「SQLSTATE[HY093]: Invalid parameter number: parameter was not defined」が出て動かない。これを、

$sql = 'select id from bar where foo_id = :id';
$result = $db->query($sql, array('id' => 1));

に変えると動く。

つまり、プレースホルダーで指定されたパラメータ以外をbindする値として渡すと、エラーが出るらしい。この辺の仕様ってPHPのPDO関連のドキュメントには書かれていないっぽいけど、これはバグなのか仕様なのかどっちだろう

Published At2006-05-25 00:00Updated At2006-05-25 00:00

日記
Zend_Db_Tableにシリアライズしたデータを格納する方法は?Edit

text型(blogblobでもいいけど)のカラムを一個作っておいて、コードからはそれを連想配列として扱いつつ、DBに書き込む前にseriailizeして保存、DBから取得する際にはunserializeしてから取得したいわけだ。

保存する方だけならば、

class Foo extends Zend_Db_Table
{
public function insert(&$data)
{
$data['bar'] = serialize($data['bar']);
return parent::insert($data);
}
// updateも同様
}

とかすればいいけど、読み込む際に自動的にunserializeするいい方法はないだろうか。

読み込みの実体はZend_Db_Table_RowとかZend_Db_Table_Rowsetクラスが受け持っているせいで、Zend_Db_Table側に直接読み込み全体をハンドリングする口がない。一応Zend_Db_Table::fetchRowをoverrideすれば、1行単位での読み込みはフックできるけど、fetchAllとか配列渡しのfindとかには対応できないしなー。

というのを昨日から考えているんだけどまだいい方法を思いつかない。

Published At2006-05-26 00:00Updated At2006-05-26 00:00

日記
Zend_Db_Tableにシリアライズしたデータを格納する方法 その2Edit

外部から解決する方法をいろいろ試してみたけれど、結局きれいに対応するのは無理っぽい。っつーか外部からの対応だと、不完全な方法しか思いつかね。

ってことで、直接Zend_Db_Table_Rowを書き換える汚い方法で対処してみた。

class Zend_Db_Table_Row
{
public function __construct($config)
{
....
} else {
$this->_data = (array) $config['data'];
if (is_callable(array($this->_table, 'fetchCallback'))) {
$this->_table->fetchCallback($this->_data);
}
}
}
}

なんてものを追加してしまう。すると、データ付きのRowが生成されるときに、そのZend_Db_TableオブジェクトにfetchCallbackというメソッドがあれば、データハッシュを引数にしてそのメソッドを呼び出す。そうしておけば、

class Foo extends Zend_Db_Table
{
public function insert(&data)
{
$data['bar'] = serialize($data['bar']);
return parent::insert($data);
}
// updateも同様
public function fetchCallback(&$data)
{
$data['bar'] = unserialize($data['bar']);
}
}

なんて感じで、読み書きでの自動シリアライズ、アンシリアライズを書けるようになる。ひとまずしばらくこれでごまかしておこう。2行の追加程度ならば、Zend Frameworkのバージョンアップ時の追随もそれほどつらくないだろうし。

Published At2006-05-26 00:00Updated At2006-05-26 00:00

日記
URIのホスト名部分Edit

Zend_Filter::isHostname()にd.hatena.ne.jpとかを食わせるとfalseが返ってきて、中を見たら、

'/^(?:[^\W_](?:[^\W_]|-){0,61}[^\W_]\.)+[a-zA-Z]{2,6}\.?$/'

にマッチしないんで、falseになっているらしいんだけど、ホスト名の各要素は2文字以上でなければならない、なんて規則はないよね?

'/^(?:[^\W_]((?:[^\W_]|-){0,61}[^\W_])?\.)+[a-zA-Z]{2,6}\.?$/'

にすればいいのかな?

Published At2006-05-28 00:00Updated At2006-05-28 00:00

12