字句を制限することで生PHPをテンプレート化する

Webを作るときにテンプレートエンジンがあると普通は開発が楽になると思う。しかし、PHPの場合はある特徴があるために、テンプレートエンジンが冗長に感じることがある。
それは、他の多くの言語では平で書くとプログラムとみなされるが、PHPの場合は平で書くと標準出力とみなされる点(<php…?>の中がプログラムになる)。要するに、PHPはそのものがテンプレートエンジンみたいな印象を受ける。
しかし、現実は甘くない。Smartyみたいなテンプレートエンジンを使っていないプロジェクトのコードだと、MVCのVの部分を見ても、物凄いコードが登場したりすることがある。これは良くない。
テンプレートエンジンを使うと何故Vの部分が綺麗になるのかという理由の一つに、プログラムコードを書くことが出来ないというのがあると思う(ちなみにSmartyには{php}があるのでその限りではないけれども)。テンプレート言語の範囲でしか記述できないという制約があるのでロジカルな部分が排除される。
そこで、ロジカルな部分を排除できれば元々テンプレートエンジンのような言語であるPHPのままでテンプレート化できるのではないのかなとか思った(ただしデザイナーがテンプレート書くような場合はまた話が違うとは思う)。
では、実際にはどうするのか。コードの字句レベルでの制限を加えればロジカルなコードを排除できないだろうかと考えて、禁止字句を書いている箇所を出力するコードを書いてみた(validator.php)。

<?php
if ($argc !== 3 || !is_file($argv[1]) || !is_file($argv[2])) {
echo 'parameter error' . "\n";
exit;
}
$config = parse_ini_file($argv[1]);
$source = file_get_contents($argv[2]);
$original = file($argv[2]);
$tokens = token_get_all($source);
foreach ($tokens as $token) {
if (is_string($token)) {
continue;
}
$tokenName = token_name($token[0]);
$tokenSource = $token[1];
$tokenLineNumber = $token[2];
if (array_key_exists($tokenName, $config)
&& strtolower($config[$tokenName]) == 'off') {
echo str_pad($tokenLineNumber, 5)
. ' | '
. str_pad($tokenName, 30)
. ' | '
. str_pad($tokenSource, 15)
. ' | '
. trim($original[$tokenLineNumber - 1])
. "\n";
}
}

コマンドラインから実行できて、例えば

$ php validator.php ./token.ini /usr/local/php/lib/php/HTTP/Request.php

のように実行すると、こんな出力が得られる。

311   | T_FOREACH                      | foreach         | foreach ($params as $key => $value) {
553   | T_FOREACH                      | foreach         | foreach ($value as $k => $v) {
577   | T_FOREACH                      | foreach         | foreach ($fileName as $name) {
902   | T_FOREACH                      | foreach         | foreach ($this->_requestHeaders as $name => $value) {
930   | T_FOREACH                      | foreach         | foreach ($flatData as $item) {
936   | T_FOREACH                      | foreach         | foreach ($this->_postFiles as $name => $value) {
943   | T_FOREACH                      | foreach         | foreach ($value['name'] as $key => $filename) {
990   | T_FOREACH                      | foreach         | foreach ($values as $k => $v) {
1062  | T_FOREACH                      | foreach         | foreach (array_keys($this->_listeners) as $id) {
1357  | T_FOREACH                      | foreach         | foreach (array_keys($this->_listeners) as $id) {

何行目に使ってはいけないトークンが書かれているよ、というような内容。
設定ファイル(token.ini)はこんな感じ(長いので一部抜粋)。

T_FOR = "On" ;for
T_FOREACH = "Off" ;foreach
T_FUNCTION = "On" ;関数
T_GLOBAL = "On" ;変数のスコープ

判り易いのでforeachのみをOffにしてる。因みに、設定ファイルの元ネタはPHP: パーサトークンの一覧 – Manualにあるトークンの全て。
ただ、現実問題としては、こういうツールがあるだけでは甘いと思う。開発者がテンプレートを書くときに自主的にツールでチェックするというような規約は弱い。間違っているとシンタックスエラーで動かない、という方が開発者は慣れているだろうし。
で、解決策としては何かしらフレームワークが必要になりそう。フレームワークの場合はテンプレートを読み込むロジックが一元化されているのが普通だと思うので、その部分でチェックしてエラーになったらログ吐いてexitみたいな。
あともう一つの問題はトークンの制御だけで本当にテンプレートが荒地にならないかどうかというところ。とはいえ、newとかclassとかfunctionとかevalとかrequireとか、Viewではいらないだろうというような字句を制限するだけでも、割とマシなテンプレートにはなりそうな気がする。

日本郵便のサイトリニューアルについて

mixiは華麗にスルーする。
郵便番号検索というサービスを構えている加減もあって9/30時点で変更点をみていたのだけど、なかなか素晴しいと思う。
ゆうびんホームページ – 日本郵便
トップページのHTML-lintは90点という、実務では珍しい高得点。デザインもどこからともなく2.0と聴こえてきそうなグラデーション基調。
よくあるご質問・お問い合わせ – 日本郵便とかは顕著だけれども、文字の大きさや電話アイコンを作っているとか、判り易いサイトを目指したのかなと感じられる(黒電話なのが若干時代錯誤だけれどイメージは伝わり易い)。
他にも、日本郵政ホーム‐日本郵政でもそうだし日本郵便のページもそうだけど、RSSが完備されていたりする。
民営化は伊達じゃない←結論

やっておけば良かったことは今やろう

高校生のときにもっと数学を勉強しておけば良かった。若いころにもっと資格を獲っておけば良かった。
色々と過去の自分に言いたいことがある人は多い。しかし、今一度確認してほしい。それはその時でなければできないことだったのか(絶対音感とか肉体的なことなどそうでない場合は勿論あるけれども)。
勉強は今でもできる。年をとれば記憶など不利になるところは確かにあるだろう。でも、出来ないではないと思う。記憶のように不利になっている側面があるならば、別の知識によって近道を見つけたりするような有利な側面もあるのだ。
あの時勉強しなかったのは他に楽しいことがあったのではないのか。他にやるべきことがあったからではないのか。過去の自分に押し付けるのなら今の自分がやろう。それが出来ないならば未来の自分が今の自分に押し付けるだけだ。
やっておけば良かったことは今やろう。

購読フィードを棚卸し

livedoor Readerで購読しているフィードが1,000を超えたので、ざっと棚卸しをしてみた。
もう無くなってしまっているフィードもあるだろうなと思って、簡単なスクリプトを書いて調べてみる。

<?php
require_once 'HTTP/Request.php';
$export = file_get_contents('export.xml');
preg_match_all('/xmlUrl="(http.+?)"/u', $export, $matches);
$handle = fopen('result.txt', 'w');
foreach ($matches[1] as $url) {
$req =& new HTTP_Request($url);
$res = $req->sendRequest();
if (PEAR::isError($res)) {
$status = $res->getMessage();
} else {
$status = $req->getResponseCode();
}
$line = $url . "\t" . $status . "\n";
echo $line;
fwrite($handle, $line);
sleep(3);
}
fclose($handle);

結果はこんな感じになった。
HeartRails Graph
案外無くなってなかった(ただしサービス側がちゃんとステータスコードを返してくれていることが前提だけど)。404になるのは14個で、「その他」の内訳は307、401、403、406。
6ヶ月以上更新されていないフィードは77個あった。
正直、死にフィードがいっぱいあるだろうなと予想していたのだけれど、多くのフィードがちゃんと更新されているようだ。
ということで、ほとんど棚下ろす必要がなかった。

PHPマニュアルが散らばっていて嫌

phpマニュアル – Google 検索
歴史的な経緯とかは全然知らないです。自分がPHPを覚えたときには既にPHP4の時代だし。
でも、なぜこんなにマニュアルが散らばっているんだろうかと思う。ご丁寧にAdSenseまで入ったマニュアルまで見かけるし。オフィシャルページでマニュアルがダウンロードできることは知っているけれども。
勿論、サーチエンジンからwww.php.net(日本だとjp.php.netかな)に辿りつけない訳ではなくて、Googleでは微妙だけどYahoo! JAPANならそれなりの順位にちゃんいる。
ただ、関数名とかで検索するとかなり鬱陶しい。例えばこんな感じ。
php mb_convert_encoding – Google 検索
オフィシャルで検索したらいいのでは?と言われたらその通りだし、実際にそうしているのだけれども、なんでこんなに複製品が陳列されているのかわからない。

らき☆すた読んだ

らき☆すた (1) (単行本コミックス)

らき☆すた (1) (単行本コミックス)

らき☆すた (2) (単行本コミックス)

らき☆すた (2) (単行本コミックス)

とりあえず2巻まで読んでみた。空気感は好き。ただボケの理解に知識を要するのがなんともなぁ。
ボケのセンスではあずまんが大王の方が好きかな。大阪人だからだろうか。

あずまんが大王 (1) (Dengeki comics EX)

あずまんが大王 (1) (Dengeki comics EX)

ドイツのホワイトビール

最近はどこに行ってもヒューガルデンホワイトが品切れ状態なのだけれども、ドイツのホワイトビールで美味しいものを見つけた。

名前が覚えられそうになかったので、メニューを写真に撮った。ついでに、ビールも撮っておいた。
美味しい。ドイツビールはピルスナーとか黒ビール的なストロングなものの印象が強かったけれども、こういうホワイトビールもあるのだなぁと思った。