PHPの配列

PHPの配列はハッシュだけでできているので、ふつーの数値インデックスの配列と違って、要素の削除が面倒だ。unsetで要素を削除すると、歯抜けの配列になってしまう。

<?php
//0 =>"foo", 1 =>"bar", 2 =>"hello", 3 =>"world"
$array = array("foo", "bar", "hello", "world");
unset($array[1]); ///1番目の要素"bar"を消す
var_dump($array);
?>

array (size=3)
0 => string 'foo' (length=3)
2 => string 'hello' (length=5)
3 => string 'world' (length=5)

番号0,2,3の歯抜け配列になってしまった。これをforループすれば、当然エラーになる。私のようなC++のvector, C#のListばっかり使っている人間には直感的にすぐに理解できないが、C#のDictionaryと挙動は同じだ。でも、数値が連続していることが前提でないと、プログラムを組みずらい。
いろいろ調べてみると、array_spliceを使えばいいらしい。

<?php
$array = array("foo", "bar", "hello", "world");
array_splice($array, 1, 1);//1番の要素から1つ分、つまり"bar"を消す
var_dump($array);
?>

array (size=3)
0 => string 'foo' (length=3)
1 => string 'hello' (length=5)
2 => string 'world' (length=5)

面倒じゃのう。何でもハッシュだと思ってやった方が楽かもしれないね。


DB構造再編

旧TrainNaviでは路線や駅に番号を振っていたが、これは拡張性を妨げるので、やめる。例えば、数年後に山手線新駅が完成する。このとき、駅を挿入するためには駅番号をずらさなければいけない。するとあちこちのDBも同時に直さねばいかず、必ず漏れが出てデバッグが大変になる。
路線番号はもっと拘束が大きい。簡単にインポート・エクスポートなどを行うためには、邪魔でしかない。インポート時に手元のものと衝突するから路線番号を変えなければいけない、なんてことになるとすごく手間だ。
路線番号や駅番号は廃止しよう!路線名や駅名で直接selectするのでよし。PHPもJavaScriptにも連想配列があるから、むしろ文字列の方が楽だ。
今回は正確な緯度経度を基にして駅を配置するから、駅と駅の間を直線で結ぶだけでは、特に駅間距離が長いときに不恰好になってしまう。それに、常磐線と常磐快速線のように停車駅が異なるとき、経由する線路が同じなのに描画すると線路がずれる、なんてダサいことも起こりうる。なので、駅と駅の間に、任意に経由地を挿入できるようにするべきだ。そうすれば、キレイな路線が書ける。いっそのこと曲線も書けるようにした方がいいかもしれない。電車のオブジェクトを動かすのが大変だけれど。
と色々と想像は膨らむけれどこれを全部実装するのは相当な手間だな。

暫定のDB構造

  • tnline 路線テーブル
    • linename 路線名
    • linecolor 路線の色
  • tnstation 駅テーブル
    • linename 路線名
    • stationname 駅名(空欄にすると経由地を表す)
    • kilo 営業キロ
    • latitude 緯度
    • longitude 経度
  • tntrain 列車テーブル
    • linename 路線名
    • trainname 列車名(列車番号)
    • service 平日か土日か
    • trainkind 列車種類(急行とか各停とか)
    • nextlinename 直通先路線名
    • nexttrainname 直通先列車名
  • tnroute 経路テーブル
    • linename 路線名
    • trainname 列車名
    • service 平日か土日か
    • startstation 発駅
    • endstation 着駅
    • starttime 発車時間
    • endtime 到着時間

TrainNaviリファクタリング準備

LanguageTrainerがある程度完成したので、次はTrainNaviをもっと実用的なものにしたい。具体的にやらなければいけないことは次の通り(優先度順)。

  • 時刻表・列車データの充実
    • いま小田急・京王・JR中央線しかないのでさらに追加、できれば首都圏全域まで拡大したい
    • そのためには、入力の手間(すっごい面倒)のスクリプト化による大幅な省力化が必要
    • データベース形式も見直すべき
  • 画面刷新
    • 位置情報を駅に付加して地図のような画面表示をする(いまは縦一列にしか並んでいない)
    • 総武線+中央線や京王線+京王新線など、複数路線並列の場合の対処が必要
  • 描画処理の高速化
    • 特定の路線、特定の列車種類だけの表示
  • 時刻表データのファイル出力、入力
  • ターゲット列車、もしくは経路を指定して強調表示
  • 駅をクリックしたら時刻表を表示

画面表示についてはかなり大幅なリファクタリングが必要になりそうだ。初めてだからしょうがないが、ビューをもっと厳格に分離して簡単に首を挿げ替えられるようにしておくべきだった。
描画処理の高速化については、駅や路線については一切再描画が必要ないので、こいつらに対してobject.cacheを使えば相当の高速化が見込まれる。列車本体もほとんど再描画しないのでこいつにも適用するべきだ。


compromise

PHPの本を読んでいて、unlinkを利用したファイルの削除のところで、どうもわからない単語に出会った。

Whenever you access files on your hard disk directly, you must also always ensure that it is impossible for your filesystem to be compromised.
For example, if you are deleting a file based on user input, you must make absolutely certain that it is a file that can be safely deleted and that the user is allowed to delete it.
(Learning PHP, MySQL, JavaScript, and CSS, 2nd Edition P144)

このcompromiseというのは通常「妥協する」という意味なのだが、妥協では文脈と会わないし、受動態なので「妥協される」となりさらに意味不明だ。ファイルシステムを安全に保てよ、壊されないように気を付けろよ、と言っているように見えるのだが、辞書に載ってない。
web検索してみると次のようなページが見つかった。

辞書に見る”compromise”はリスクの概念に留まると思われるのですが、昨今のセキュリティ関連のニュースで用いられる”compromise”にはもっと具体的な意味、つまり不正利用、暴露、犯罪目的の利用、などが含意されているように思われます。

Merriam Websterでは、
to reveal or expose to an unauthorized person and especially to an enemy
という定義(と<>内は例文)が見られます。このような定義はAmerican Heritage Dictionaryや英和辞典に見られず、昨今のセキュリティ関連のコンテクストでの用法を他に先駆けて取り入れたものではないかと思われます。

なるほど!じゃあやはり、「ファイルシステムが危なくならないように気を付けろ(壊れないように気を付けろ?)」と言ってるので間違いなさそうだ。こんな風な単語の術後的な使い方は、専門的になるほど増えてくるのかなぁ。日本語ですら面倒なのに憂鬱だなぁ。


HTML5でグラフ

canvasを使ってグラフを描きたい。用途は、LanguageTrainerの統計機能。ペース配分に使いたい。
flotr2というライブラリを使うとラクラクグラフが書けるらしい。サンプルコードはこちら
PHPとJavaScriptを連携させるしかないが、グラフの数なども動的に変える必要があるので、次のように実装する予定。
・PHPでMySQLを使ってDB読み込みし、必要な情報をjson形式で変数に保存しておく。さらに、グラフ表示用のHTMLタグもPHPで生成する。
・JavaScript側ではグラフの描画だけを担当する。PHPで作った情報を使ってグラフ表示する。
今日は構想だけで時間が来てしまったので、ここまで。


一覧表示

六帖Webアプリ更新
一覧表示機能を追加した。PHPだけで作るのは苦しいね。$_POST[]に値を代入しておいて自ページ遷移で値を取り出す、というかなり無理のある作りになってしまった。PHPは静的テキストを吐き出す言語だから、動的な動きは苦手だ。今の仕様だとプルダウンメニューを選択した時点でページ移動することができない。これはJavaScriptを使うしかなさそうだ。本当はAjaxを使うのが一番スマートなんだろうなぁ。いずれリファクタリングして、全くページ遷移しないように書き換えてみよう。
デザインについては全く考慮なしのTABLEタグ直書きなので、大いに改良の余地がある。いま読んでいる本のCSSの内容に入ったところで、全体的なデザインを見直そう。
残りは統計機能を作れば、欲しかった機能を一通り作り終わることができる。デザインもできたら、あとはこのほぼ完全に自分用のプログラムを、他の人も使えるような仕様に拡張していきたい。


タイムゾーン

午前中にLanguageTrainerを実行したらなぜか復習の問題が1問も出題されない謎の現象が起きた。いろいろ調べてみるとなぜかSQL文の日付の条件が1日前になっている。現在日付をゲットするdateオブジェクトの値を出力すると、なんと日本時間から13時間も遅れていることが分かった。これはGMT-4だから、ニューヨークのタイムゾーンに相当する。miraiserverはニューヨークにあるのかな。

date_default_timezone_set(‘Asia/Tokyo’);

と記述することで正常に動作するようになった。現在時刻を使用するアプリケーションでは、タイムゾーンの考慮も必須になるんだな。当たり前のことなんだろうけれど知らなかった。一行で済んでしまうPHPの利便性はすばらしい。便利な組み込み関数が豊富だ。


夏の終わり

昨日色々と用事を済ますため街に出かけた。生徒にとっては夏休み最終日なので、明日からは高校生が電車に大勢集結することになるのだろう。ちょっとうんざり。自分たちもあんなのだったのだし、、と思ってやり過ごそう。
3日前にサーキュレーターのボタンが戻らなくなりショートしたと思われる異臭がして壊れたので、購入先のスーパーに電話すると修理してくれるという。レシートをなくしたと伝えるとこっちで適当に日付を書くから持ってきてください、と言われた。アバウトだ。
で、それをスーパーに持って行ったあと、電車で街へ行って、これまた壊れた携帯電話の修理が済んだので取りに行った。携帯は購入日から3年まで無料で修理してくれるという。代替機を入れてもらったポーチがかわいいので気に入っていたがこれは返さなければいけず、残念。ドコモショップで受付の発券機のボタンを店員さんが押したところ、画面がフリーズして、1分後に「発番に失敗しました。アプリケーションを終了します」と表示され、ウインドウが閉じた。するとそこにはXAMPPのアイコンが。。ということは、ドコモショップ内のどこかにサーバーがあり、サーバーと言ってもそんな大がかりなアプリケーションじゃないので適当なPCだろうけど、発券機はサーバーにメッセージを送って客待ち情報をキューに入れ、一人店員が空き次第キューに入っている客を呼び出すんだろうな。面白い仕組みだ。あ、XAMPPが入っているマシンがサーバーだろうから、発券機付属のPCか。なるほど。で、店員が使ってるPCがサーバーのhtml/phpファイルを操作すりゃあいいよね。店内には待ち人員の数や待ち時間の目安(割と正確)、番号の呼び出し用のディスプレイがあり、1人店員が空くと客が1人呼び出されるようになっている。これはどういう仕組みにすればいいのかな。発券機のアプリケーションがフリーズしても呼び出し用のディスプレイはフリーズしなかったから、また別の端末なんだな。じゃあやっぱりサーバーは別のマシンなのか。1分毎くらいにサーバーに現在の状況を問い合わせて、返ってきたテキストファイルかなんかを基にして画面表示すればいいよね。でも客の呼び出しは1分毎というわけにはいかないし、これはまた別件で割り込み待ちをしているのかな?ということを考えつつ待つと無事、携帯が戻ってきた。
ドコモショップの周りはもともと古い街なんだけれど、日本の郊外で起こっているロードサイド化の例にもれずここも駅周辺は衰退しつつあり、潰れた店の跡地に全国どこにでもあるダイソー、ドン・キホーテ、日高屋、などのつまんないチェーン店が入ってどこにでもある地方都市化しつつある。かといって老舗の店には客が少なく跡継ぎも少ない。大資本の一人勝ちになっていくんだろうなぁ。笑っちゃうようなオリジナル精神溢れる店でもやっていけるのはもう東京しかないのかな。


LanguageTrainerほぼβ版

六帖Webアプリ更新
LanguageTrainerに編集機能を付け、致命的なバグを取ってついでにいくつか機能を付けて、一通り使えるバージョンになった。miraiserverのアクセス制限については、そんなに頻繁にSQLアクセスはしないだろうということで、とりあえず放置。あとはデータベース次第なので、問題を増やしていきます。


Windows8.1(64bit)+XAMPPユーザーのみなさん

通常使用のPCを新旧交換した。
CPU速度は目算1.5倍、メモリは2GBから4GBに、同じWindows8.1だけど32ビットから64ビットOSに、ディスプレイは15→21インチと作業環境が劇的に改善した。
まずFireFoxがフリーズしない。すばらしい。FireFoxはメモリが足りなくなるとひたすらGCするのか悲鳴を上げてフリーズする。これがメモリが増えてなくなった。
ディスプレイが広い。1024*768ではそろそろ限界だった。会社のPCが変わりフルHDになったのに、リモート接続すると画面が狭くなっていてもったいなかった。
ところが、自作PHPアプリケーションを動かしてみるとなぜか遅い。。SQLの実行に毎回2秒くらいかかる。前のPCでは一瞬だった。
調べてみると、どうもWindows7/Vista以降はlocalhostの名前解決にDNSを使っているらしい。こりゃ遅い。
http://lazesoftware.com/blog/12/0926/

なのでたった一か所変えるだけで劇的に速度改善した。以下引用。

// これを
mysqli_connect('localhost', 'user', 'password', 'dbname');
// こう変更すれば良い...
mysqli_connect('127.0.0.1', 'user', 'password', 'dbname');

ローカルでWebアプリケーションを開発している人は気を付けてください。
ここには書いてないけど、32ビットOSでもこの現象は起こらないと思われる。変更前も変更後もWindows8.1だったので。

古いPCは作業場で電源入れっぱなしだが突然の再起動は起こらない。おそらく、夏になって電力消費が増え家全体の電圧が下がっていたところ、老朽化したマザーボードのコンデンサーが電圧差に耐えられなくなり再起動を繰り返していたと思われる。時々PC用の間接照明の明かりが暗くなっていたので。