2010年12月27日月曜日

PHPで CSVをダウンロードするための参考サイトとサンプルコード

CSVをダウンロードするWebアプリをPHPで実装する方法。
しばしば必要になるが、そのたびに調べ直してるので、後日のためにまとめてみる。



まとめるとこんな感じか。
$fileName = 'ダウンロードして保存する時のファイル名.csv';
$fileName =  mb_convert_encoding($fileName, 'SJIS-WIN');

header('Content-Type: application/x-csv');
header("Content-Disposition: attachment; filename=$fileName");

$fp = fopen('php://output', 'w');

$rows = /* 配列の集合(DBから取得したデータとか) */

foreach ($rows as $row) {
    mb_convert_variables('SJIS-WIN', mb_internal_encoding(), $row);
    fputcsv($fp, $row);
}

fclose($fp);

2010年12月21日火曜日

PHPの DateTimeオブジェクトは比較演算子で大小を比較できる

大なりや小なりやイコールで大小(前後)を比較できたら便利だなと思い、試してみた。

$time = new DateTime('2011-01-01 01:01:01');
$aftr = new DateTime('2011-01-01 01:01:02');
$same = new DateTime('2011-01-01 01:01:01');

var_dump($time >  $aftr);    // => false
var_dump($time >= $aftr);    // => false
var_dump($time == $aftr);    // => false
var_dump($time <= $aftr);    // => true
var_dump($time <  $aftr);    // => true

var_dump($time >  $same);    // => false
var_dump($time >= $same);    // => true
var_dump($time == $same);    // => true
var_dump($time <= $same);    // => true
var_dump($time <  $same);    // => false

比較できるんだ。知らなかった...

2010年12月10日金曜日

PHPで配列と配列を結合する

PHPの配列はarray_merge()でマージできるが、数値のように+演算子でも結合できる。しかし、微妙に結果が違う。


KEYのある配列の場合

//array_merge
var_dump(array_merge(array('foo' => 1, 'bar' => 2), array('foo' => 3, 'baz' => 4)));

array(3) { ["foo"]=> int(3) ["bar"]=> int(2) ["baz"]=> int(4) }

//+演算子
var_dump(array('foo' => 1, 'bar' => 2) + array('foo' => 3, 'baz' => 4));

array(3) { ["foo"]=> int(1) ["bar"]=> int(2) ["baz"]=> int(4) }

同じKEYがある場合、array_merge()だと後の配列で上書きするのに対し、+演算子だと先の配列が勝つようだ。



KEYのない配列の場合
//array_merge
var_dump(array_merge(array('foo', 'bar'), array('foo', 'baz', 'quux')));

array(5) { [0]=> string(3) "foo" [1]=> string(3) "bar" [2]=> string(3) "foo" [3]=> string(3) "baz" [4]=> string(4) "quux" }

//+演算子
var_dump(array('foo', 'bar') + array('foo', 'baz', 'quux'));

array(3) { [0]=> string(3) "foo" [1]=> string(3) "bar" [2]=> string(4) "quux" }

array_merge()は全ての配列の値を入れた配列を作ってくれるが、+演算子だとインデックスをKEYとみなして同じインデックスがある限り先の配列の値しか残らない。


基本的にarray_merge()を使う習慣にしておいた方が無難そうだ。



参考:ひとつまたは複数の配列をマージする - PHP 5.3 日本語マニュアル

2010年12月7日火曜日

PHPの htmlSpecialChars()の 第3引数(文字コード)の調査メモ

そもそも

基本的に内部的な文字コードは(ソースファイルもDBもその他の設定も)全てUTF-8にしておき、POSTやGETなどで入力値を受け取る時には入力値をUTF-8に変換してから使うのが良いと思うし、そうすれば漏れがない限りはhtmlSpecialChars()等で出力時に不正文字コードを気にする必要はない。



しかし

現実的にはPOST/GETで受け取る以外にも下記の様に様々な方法でデータが入ってくることもある。

それぞれデータを取り出す時に適切に文字コード変換すべきだが、やっぱりいつか誰かが漏らしそう。

なので、やはり出力時にも不正な文字コードは弾いた方がよい。



で、調べてみた

2009年の後半にいくつかのブログでこのことが論じられていた。(そういえば読んだ記憶が...。詳細は下の方の参考リンクを参照。)
中でも「htmlspecialchars - 第45回PHP勉強会@関東 :: handsOut.jp」が簡潔でわかりやすかった。
PHP5.2.5以降を使い、htmlspecialchars()の第3引数にUTF-8を指定するのが一番堅実のようだ。

蛇足だが、もしUTF-8以外でWebページを入出力したい場合は、mb_http_output()とob_start()を使って出力完了後に文字コードをSJIS-WINなどに変換させるようにしておいて、そこにUTF-8で出力するのが良いと思う。(処理量が多いとオーバーヘッドが気になる?)



以外な落とし穴が

しかし、htmlspecialchars()の文字コード検出には思わぬ落とし穴があった。
htmlspecialchars()は不正な文字コードを見つけても、PHPの設定でdisplay_errorsがfalseの場合しかWarningを出さない
  • display_errors = true → Warningを画面にもログにも出さない
  • display_errors = false → Warningをログにも出す(画面には出さない)
これでは、開発環境では文字コードが不正になりうる箇所に気づかないまま、本番環境でWarningを出しまくるかもしれない。

これは意図的なものなので、修正されない可能性が高そう。(参考:display_errorsが謎の副作用を持っている箇所について - muddy brown thang
また、@htmlspecialchars()に@(アットマーク)を付けてもログへのエラー出力を抑制できなかった。

Warningを出さないようにする対策としては、htmlspecialchars()の手前で強制的に文字コードを変換するという手がある。
$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
echo htmlSpecialCahrs($str, ENT_QUOTES, 'UTF-8');
現在のサーバ性能とPHPの速さなら、こんな富豪的な重複処理もあまり問題にならない環境が多い。
mb_convert_encoding()とhtmlSpecialChars()の検出基準(?)が違うというようなことをどこかで読んだ気がするんで、その場合はこれでもWarningが出るのだろう。
でも、どうせmb_convert_encoding()するのなら、そもそもhtmlSpecialChars()での文字コード指定は要らないか。

ただし、本道としては、せっかく出してくれるWarningを手がかりにして、該当箇所で適切な文字コード変換をするようコードを修正するのが筋だろう。
PHPのWarningはset_error_handlerで捕まえられる。



もう1つ

htmlspecialchars/htmlentitiesはBMP外の文字を正しく扱えない - [php] - 徳丸浩の日記」という落とし穴もあるようだが、これはPHPの5.3.2でFixした。(5.2系は?)
また、(線文字Bは置いておいて)一部の漢字を「使えません。仕様です。」で済ませられるなら、こちらの問題は黙殺できそうだ。



参考

2010年11月28日日曜日

HMAC方式で認証用のハッシュを生成するメモ


HMAC
(Keyed-Hashing for Message Authentication Code)とは?

HMACはハッシュ(Message Digest)生成アルゴリズムで、MD5やSHA1、SHA2等と組み合わせて使う。(それぞれ「HMAC-MD5」「HMAC-SHA1」などと呼ばれる。)



なぜ認証用のハッシュがHMACでなければいけないのか?

HMACでないハッシュ関数を認証用のハッシュ(トークン)生成に使うと、秘密鍵を知らなくても任意のハッシュを生成できるケースがあるらしい。(参考:Kazuho@Cybozu Labs: Re: はてな認証 API

よく理解していないけど、ハッシュアルゴリズムがデータブロック単位で処理することに起因している?
暗号化においてCBCでIVが固定の場合と同じような問題?(参考:floatingdays: PHPで AES方式 (Rijndael-128)で暗号化するメモ

それに対してHMACでは、変換元の値とは別に指定する秘密鍵組み合わせることにより、上記の問題を回避しているらしい。(参考:HMAC: Keyed-Hashing for Message Authentication



HMAC方式でハッシュを生成する方法

今どきのプログラム環境は言語レベルで実装してるみたい。

PHP 5.1.2以降の場合
HMAC 方式を使用してハッシュ値を生成する - PHP 5.3 日本語マニュアル

PHP 5.1.1以前の場合、外部ライブラリとしてmhashが必要 (参考:導入 - PHP 5.3 日本語マニュアル
ハッシュ値を計算する - PHP 5.3 日本語マニュアル

Javaの場合
試験管のなかのコード :: JDK 1.4.x 環境で HMAC with the SHA256 を使用する方法



参考:

2010年11月21日日曜日

PHPで 「Webページの有効期限が切れてます」となる時の傾向と対策

PHPでフォーム等を作った場合、Webブラウザの戻るボタンやJavaScriptのhistory.back()で前のページに戻った時に「Webページの有効期限が切れてます」と表示されることがある。

上記はIEの場合で、ブラウザによって少し挙動が違う(下記)。
いずれもページを更新(リロード)するとサーバにPOSTが再送信され、ページが表示される。
  • IE
    • 上記(IE8の例)のような画面が表示される。
  • Firefox
    • 「このページを表示するにはフォームデータを再度送信する必要があります。フォームデータを再送信すると以前実行した検索、投稿や注文などの処理が繰り返されます。」という確認ダイアログが表示され、「再送信」ボタンと「キャンセル」ボタンが表示される。「再送信ボタン」をクリックするとページが表示される。
  • Chrome
    • 「フォーム再送信の確認
      このウェブページを正しく表示するには、先ほど入力したデータが必要です。データをもう一度送信することは可能ですが、このページで行った操作をすべて繰り返すことになります。データを再送信してこのページを表示する場合は [再読み込み] をクリックしてください。」というメッセージのみの画面が表示される。
  • Safari
    • このようなダイアログが表示される。(Windows版で確認。Mac版は分からない。)



犯人はだれだ?


原因は、PHPでSESSIONを使うと(デフォルト設定では)自動でキャッシュ制御用のHTTPヘッダーが送出され、それによりクライアント側のキャッシュが使用不可にされるため。(参考:floatingdays: PHPでブラウザキャッシュを有効にする

つまり、下記条件を全て満たした場合にこの現象が発生する。
  1. HTTP POSTで遷移してきた。
  2. SESSIONを使っている。(session_start()してるか、php.ini等でsession.auto_start=1に設定している。)
  3. 次のページに行ってから、ブラウザの履歴機能(JavaScriptのhistory.back()を含む)で戻ってきた。



じゃあどうすればいいの?

対策として有名なのは、session_start()する前に、session_cache_limiter('none')とすること。
session_cache_limiter('none');
session_start();
これにより、SESSIONを使っても余計なHTTPヘッダーが送出されなくなる。

または、php.ini等でsession.cache_limiterに"none"を設定しても同じことになる。(おそらく元ネタはこのあたりだろう → PHP: session_cache_limiter - Manual

実際にこれで問題は解決する。



異論反論オブジェクション! [shut very bad!]

しかし、「PHP/「ページの有効期限切れ」対策 - Glamenv-Septzen.net」によると、これはPHPが想定しているパラメータではなく、お行儀のよいやり方ではないらしい。

'none'というパラメータは正しいパラメータではなく、それゆえに何もHTTPヘッダーを送出しないという挙動になるらしい。
(ただし、もし「規定外のパラメータはスルーする」というのが意図した仕様だとしたら、'none'でも何でも「正しいパラメータ」だけど。)

上記の記事ではsession_cache_limiter('none')ではなくsession_cache_limiter('private_no_expire')を推奨している。
「ページの有効期限切れ」をsession_cache_limiter()で解決 - shinyanakaoのよすがブログ」でも同様にprivate_no_expireを推奨している。

しかし、実際にsession_cache_limiter('private_no_expire')を使うと、やはり余分なHTTPヘッダーが送出される。

private_no_expireの場合、(privateに比べて)Expiresが送出されなくなるが、「Cache-Control: max-age=(session.cache_expire ぶんだけ未来)」が送出されるため、やはりブラウザに影響が出てしまう。(参考:現在のキャッシュリミッタを取得または設定する - PHP 5.3 日本語マニュアル
Firefoxでは問題ないが、IEだとリロード時にもキャッシュを使ってしまい、サーバからのリロードができなくなるようだ。(参考:Webアプリケーション開発ラボ by NPO情報活用センター - PHP:キャッシュ問題について。PHP Tips|ワークスポット・ジェーピー
おそらくsession.cache_expireで設定されている期間はキャッシュが有効になるのだろう。(Expiresでそう指定しているのだから、IEは悪くない。)

なので、お行儀が悪くてもsession_cache_limiter('none')を使うしかないのでは?('none'じゃなくて'hoge'でも'hage'でも「正しい」パラメータ以外なら何でもいいけど。)



新たな選択肢

しかし、こういう手もあるよ。
session_start();
header('Expires:'); //下記「余談」の追記も参照
header('Cache-Control:');
header('Pragma:');

header()でセミコロンの右に何も書かないと、PHPは何も送出しないようだ。
これにより、session_start()のHTTPヘッダー送出を上書きし、結果的に何も送出しない。

session_cache_limiter('none')より冗長だが、明示的という意味ではいいかもしれないと思っている。
(キャッシュを有効にしたい場合にも応用が効く。)



余談

上記のようにブラウザキャッシュの無効化を無効化すると、当然ながらSESSIONの最新情報が反映されていないブラウザキャッシュをブラウザが表示してしまうので注意。

(2011/1/7 追記)
IEはキャッシュがあり、かつ、そのキャッシュがExpiresを何も指定されていないと、アドレスバーにURLを直接入力された場合やリダイレクトした場合などにサーバにアクセスせずにキャッシュの方を使ってしまう。(Firefoxはその場合もサーバにアクセスしてくれる。)
ブラウザの履歴機能を使うためにキャッシュはさせたいが、上記の場合にはサーバにアクセスさせたい場合は、Expiresで-1を指定すると良いようだ。
header('Expires: -1');
ログイン管理をする場合などはこれをやっておいた方が良さそう。
(追記終わり)

また、POSTのパラメータに「チケット」(=ワンタイムトークン)を入れることによる二重POST防止を推奨するのは正しい。というか二重POSTを確実に防ぎたいと思ったらこれしかない。


2010年11月16日火曜日

大手サイトがやっている自サイト専用のURL短縮サービス

思いつくものをまとめてみた。
bit.lyによる独自ドメインURL短縮サービスで日本人にあまり馴染みのないもの(NY Timesとか)は除外した。

サイト
短縮URL
備考
Google Maps
FeedBurner
goo.gl
Google Mapsは goo.gl/maps/xxxx
FeedBurnerは goo.gl/fb/xxxx
その他のサイトの場合、 goo.gl/xxxx
YouTube
youtu.be
後ろに動画のIDを付けると、その動画の短縮URLになる。
例: http://youtu.be/4qCbiCxBd2M
Yahoo!
yhoo.it
powered by bit.ly
uk.yahoo.comやfr.yahoo.comは短縮してくれるが、
yahoo.co.jpは対象外。なぜかtw.yahoo.comも対象外。
Flickr
flic.kr

Delicious
icio.us
ドメインハックの先駆者がこんな形で再利用されるとは。
Bing
binged.it
短縮URLは既に機能しているが、
URL生成はまだプライベートBeta。
Amazon
(USのみ)
amzn.com
後ろにASINを付けると、その商品ページの短縮URLになる。
例: http://amzn.com/B002FQJT3Q
Kindleの場合、「amzn.com/k/xxx」のようだ。
アソシエイトはできるのかな?
Amazon
amzn.to
powered by bit.ly
こちらはamazon.co.jpも対象。
Facebook
fb.me

Twitter
t.co

foursquare
4sq.com

MySpace
mysp.ac
powered by bit.ly
Ustream
ustre.am

Dailymotion
dai.ly
powered by bit.ly
Scribd
scr.bi
powered by bit.ly
楽天
r10.to
どこで生成できるか分からなかった
mixi
mixi.at

ニコニコ動画
nico.ms

はてなブックマーク
htn.to
powered by bit.ly (2011/3/21 訂正)
PIXIV
p.tl

日経新聞
s.nikkei.com
powered by bit.ly


日経新聞のサブドメインを使うやり方は好感が持てる。
Bingはよく考えたら自サイト専用じゃないけどまあいいや。
ところでyhoo.itはYahoo! Italia(it.yahoo.com)と間違えそう。


(2011/3/21 追記)
htn.toは、はてなブックマークだけでなく、はてな全般で使われているみたい。(これを書いた後で変わった?)
また、bit.ly proを使ってるわけではないようだ。
(追記終わり)


参考:
Bit.ly、月間47億クリック。Pro版も好調、Yahoo、MySpaceらも採用
bit.ly | Basic | a simple URL shortener
JSTwi


2010年11月10日水曜日

Microsoftの Webページ埋め込み用画像拡大ビューワーサービス Zoom.it

Zoom.itはMicrosoftのLive Labsが作ったWebページに埋め込める画像Viewer。
もともとはSeadragonという名前だったようだ。(参考:巨大な画像のビューアーを作ってくれる『Seadragon』 - 100SHIKI

画像のURLを指定すると、その画像をZoom.it側で取り込んで、表示できるようになる。
Zoom.it側で取り込むので、見るときはZoom.itの発行するURLで見るか、埋め込み用のJavaScriptを自分のサイトに埋め込んで見る。

画像のファイルサイズは無制限のようだ。(参考:Zoom.it - FAQ
Web公開用画像の外部ストレージサービスとしても使えるのかな...!

そしてこれ、画像だけでなく、実はWebページのキャプチャもしてくれる。URLとして、画像のURLの代わりにWebページのURLを入力するだけ。
UTF-8のページなら日本語でも問題なくキャプチャできた。(Shift_JISの場合は文字化けした。)

注意点としては、一度Zoom.itに取り込ませた画像は削除も変更もできない。「あなたがそのURLを公開しない限りは見つかることはないから大丈夫だよ」(Zoom.it - FAQ)と言われても、公開してしまったら後で困るかもしれないので慎重に?

これを作ったMicrosoftのLive LabsはBing部門に吸収された(参考:Microsoft Live Labs)ようだが、今後Zoom.itはどうしていくつもりなんだろう?
FlickrのようなCGMとして展開していかないのかな。


ところでZoom.itはGoogle Analyticsが仕込んである。MSも自前でアクセス統計を持ってなかったっけ?

2010年11月9日火曜日

あなたの知らないbit.lyの便利機能

URL短縮サービス最大手のbit.ly。Yahooなど大手サイトの短縮も請け負ってもはやURL短縮サービスの代名詞になりつつある。
そんなbit.lyだが、URL短縮以外のサービスもやっていることについては意外と知らないのではないだろうか?


1. 後ろにプラスでクリック数やTwitterでのつぶやきを表示


短縮URLの後ろに"+"(プラス)を付けると、その短縮URLのアクセス統計が見られるのは有名。

でもTwitterでのつぶやき(最大99件)等も見られるようになっているのは知らなかった。
Twitterのつぶやきには、bit.lyで短縮されたものだけでなく、goo.glやTinyURLで短縮されたリンクも含まれて表示されている。BackTweetsから引っ張ってきているようだ。
URLがトップレベル等の場合、その配下の短縮URLも含めたTweetが表示される。(BackTweetsを使うからそうなるんだろう。)
下記の例は「はてなブックマーク」のトップページの短縮URLの統計ページだが、はてなブックマークのトップページだけだなく、はてなブックマーク内の全ての短縮URLのTweetが表示対象となっている。
例: bit.ly statistics for (はてなブックマーク)

また、クリック数はj.mpと共有しているようだ。→ http://j.mp/DeWI+

ちなみに、amzn.toなどのbit.lyの専用短縮URLの場合、プラスを付けるとbit.lyのページにリダイレクトされて統計が見られる。
例: http://amzn.to/CB7N+



2. QRコード

goo.glでは短縮URLの後ろに".qr"を付けるとQRコードが表示されるが、bit.lyもいつの間にか(?)実装していた。
bit.lyの場合、短縮URLの後ろに".qrcode"を付けるとQRコードが表示される。
例: http://j.mp/DeWI.qrcode

goo.glのQRコードより大きい。(goo.glには負けないという意気込みを感じる?)

QRコードは(株)デンソーウェーブの登録商標です。



3. 人気の動画を一覧表示

統計から人気の動画を選び、一覧表示しているようだ。 → bitly.tv | What the world is watching now



4. a.ly

http://a.ly にアクセスするとbit.lyにリダイレクトされる。
しかし残念ながら(?)このa.lyは短縮URLには使えないようだ。

mod_pagespeedとは

Google製のApacheモジュール。インストールするだけでWebサイトを高速化できる。
Apache2.2向けに、CentOS用とUbuntu用が用意されている → Page Speed Downloads


以下は参考ページのリンク。

概要
Google、Apache モジュール「mod_pagespeed」をリリース - スラッシュドット・ジャパン
mod_pagespeed所感 - 最高のコンピューティング環境とは?


具体的な使用例
mod_pagespeed をちょっとだけ試してみた - 酒日記 はてな支店
mod_pagespeedをEC-CUBEを使って早速試してみる - なげっぱなし日誌
紀子さん@へぼぷろぐらまの日常 mod_pagespeedいれてみた。
mod_pagespeedを入れてみた - でぶろぐ


詳しい解説
続・mod_pagespeedの各Filterと設定について ハブろぐ - havelog.ayumusato.com
mod_pagespeedについての考察とか | Yet Another Geek Blog(日々の葛藤日記 Ver.2)


インストール
さくらのVPSにGoogleのmod_pagespeed入れてみた ハブろぐ - havelog.ayumusato.com


感想
けっこうドラスティックに変えちゃうみたい。
JavaScriptはMinifyするらしいけど、IE用の条件付きコンパイルは残してくれるのかな?
「Elide Attributes」がHTML5には対応してるかは要確認。
既存のサイトへのいきなりの適用は危険そう。新しいサイトなら開発段階からこれを使って作ってくのはありかも。
WordPressやRailsなどの代表的なCMSやFrameworkで「使えた」という報告が上がってくれば普及するかも?
Google App Engineでも同じようなことやればいいのに?(オプションとして提供するとか。)

2010年10月29日金曜日

jQuery UI 1.8.6の Minified CSS

jQuery UIのバージョン1.8.6がリリースされていた。

jQuery UI - Documentation: UI/Changelog/1.8.6

Change Logに「Minify CSS」と書いてある。
jQuery/jQuery UIは、JavaScriptはMinifyされたものも用意されているが、jQuery UIのCSSはなぜかMinifiyされたものが提供されていなかった。
これはちょっと嬉しいかもなので調べてみた。


変更内容はこんな感じらしい → Commit af582b97a70e955432fdf4123891b75d2f2c68c5 to jquery's jquery-ui - GitHub
テーマ「base」にminifiedなCSSが追加されたようだ。

Google Codeで確認してみた → jquery-ui - Project Hosting on Google Code
確かに追加されている。

GoogleのCDNで見てみた → http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/base/minified/jquery-ui.min.css
(最初のコメント以外は)1行で書いてある。


良い方向だと思うが、「base」以外のテーマはMin版が無いのが残念。(なぜbaseだけ?)

また、アイコンの背景画像のURLが「images/...」から始まっているので、そのままではimageディレクトリへの参照にならない。
minifiedディレクトリの中身をbaseディレクトリの中に移動してから使えということかな?(Google等の)CDNを使っている場合は参照が正しくないのでアイコンが表示されなくなる。

あと、minifiedというディレクトリに入ってるのに、ファイル名に「.min.css」って付けているのが冗長だと思うが、上記のようにファイルの移動をした時に上書きしないようにということかな。

2010年10月27日水曜日

1文字のセカンドレベルドメイン

1文字のセカンドレベルドメインで、現在活用されているものを調べてみた。
(セール中のものはたくさんあったが除外した。)


TLDドメインURL短縮リダイレクト補足説明
cn6.cn
中国の動画共有サイト

g.cn
Google中国(谷歌)
coe.co

準備中?

t.co
by Twitter
comq.com
Quest

x.com

PayPal X

z.com

休止中
ly0.ly


1.ly
webciety

2.ly


3.ly


4.ly
2.lyと同じサイトと思われる

6.ly
2.lyと同じサイトと思われる

7.ly
2.lyと同じサイトと思われる

8.ly
2.lyと同じサイトと思われる

a.ly
bit.ly

c.ly


g.ly
grooze.com

o.ly


p.ly
re.p.lyのエイリアス

s.ly

準備中?

v.ly
2.lyと同じサイトと思われる

x.ly

準備中?

y.ly


z.ly

準備中
mpj.mp
bit.lyの別サービス
neti.net

休止中?

q.net

休止中
nuu.nu
サービス終了
orgx.org

X.Org
w.org
Wordpress.org
tlp.tl
by PIXIV
to5.to


vg1.vg




やはり短縮URLサービスが多い。
bit.lyはa.lyじゃなくて、re.p.lyみたいにt.lyを取得すればいいのに。

それにしてもlyの1文字っぷりがもはや清々しい。

他にもあれば情報ください!

(2010/11/05 u.nuを追加)
(2011/03/07 5.toを追加)
(2015/03/01 w.orgを追加)

2010年10月26日火曜日

ファイル1つだけで出来ている 便利なPHP製ツールいろいろ

PHPライブラリは新時代に入った。定番だったphpMyAdminやPEAR::Mailはもう古い。最近は1ファイル配置するだけで簡単に使える便利なツールが増えてきた。

例えばこんなの。



次は1ファイルのフレームワークだね。(Google Code上にはもうたくさん公開されてるけど...)
あるいは1ファイルのブログシステムやWikiか?

2010年10月9日土曜日

Googleの 各サービス個別のLabsを集めてみた

Google Labsに入っていない、Googleの各サービスのLabs(実験的機能)を集めてみた。


  • TestTube
    • YouTubeのLabs
    • HTML5で動画を見るにはここで設定するみたい
  • Google Maps Labs
    • Googleマップの右上の緑色のフラスコのアイコンから設定できる
    • URLの短縮化、地図の回転、周辺情報の表示(Google Palces?)、緯度経度の表示(ツールチップ or マーカー)など、ちょっと便利な機能がある
  • GMail Labs
    • GMailにログインして、右上の「設定」リンクまたは緑色のフラスコのアイコンから遷移できる
    • 「宛先入れ忘れ防止」「既読ボタン」「既読ラベルを非表示にする」など、いろいろ便利な機能がある
    • Google AppsのGMailでも使える
  • Google Calendar Labs
    • Googleカレンダーにログインして、右上の「設定」リンクまたは緑色のフラスコのアイコンから遷移できる
    • Google Appsのカレンダーでは使えない
  • Blogger in Draft
    • BloggerのLabs
    • Bloggerユーザーなら、こっちをデフォルトにすることをお薦めします
  • Google Experimental Search
    • Google Labs内にある、「Google Search Labs」なもの。(これだけGoogle Labsに入っている。)
    • でもGoogleサジェストとかGoogleインスタントはここを経由せずにリリースされた。(サジェストがGoogle Labsに居たころは、まだExperimental Searchが無かったか。)


Google DocsとかPicasa WebとかGoogle AnalyticsとかAdSenseにもあっても良さそうだけど、無いのかな?

2010年9月22日水曜日

フリーで使えるJavaScriptと CSSの CDNいろいろ

httpsが使えるのはGoogleとMSのみ。
httpsに拘らないならCached Commonsがライブラリ豊富で便利そう。
でも使いたいライブラリがGoogle Libraries APIで間に合うならGoogle Libraries APIでいいんじゃないかな。レスポンス速度が速いし。
(レスポンス速度はminファイルのロード時間を4回計った2~4回目の平均値。状況によって変わってくるだろうから、参考程度に。)


Google Libraries API

  • 主要なJavaScriptライブラリをホスティングしている
  • バージョン指定でメジャーバージョンのみの指定や、マイナーバージョンまでの指定等が可能
  • https可
  • YUIはバージョン2しかない
  • ブラウザキャッシュは1時間 or 1年間(参考:floatingdays: Google AJAX Libraries APIのブラウザキャッシュ期間
  • レスポンス速度
    • jQuery:0.069秒 
    • YUI 2 YUI Loader:0.066秒


Microsoft Ajax Content Delivery Network - ASP.NET Ajax Library
  • ASP.NET関連以外ではjQuery関連の3つをホスティングしている。Validationプラグインは便利かも?
    • jQuery
    • jQuery UI
    • jQuery Validationプラグイン
  • https可
  • ブラウザキャッシュは1年間(max-ageとExpiresが違う気がする?)
  • レスポンス速度
    • jQuery:0.161秒


YUI
  • httpsは使えない
  • JavaScript、CSSをそれぞれ1つずつにまとめられる(Combine Files)のは便利
  • ブラウザキャッシュは10年間
  • レスポンス速度
    • YUI 2 YUI Loader:0.181秒


Cached Commons


JsLoad: Remote loading API of JavaScript library
  • Google App Engineで作られている
  • 2008年10月から更新されていないようだ


JavaScript Host(←※リンク切れ)
  • 閉鎖しちゃったみたい


(2010/10/19 追加)
jQuery Code Server
  • jQuery自身によるjQueryのホスティング
  • ダウンロード用のファイルをそのままhotlinkしてよいことにしたようだ
  • jQuery UIとかプラグインは提供しないのかな?



参考

2010年9月19日日曜日

監視ツールMonitの調査メモ

フリーでオープンソースなサーバ監視ツール「Monit」についての調査メモ。参考サイトの羅列がメイン。


監視対象



できること
  • プロセスを再起動
  • プロセスを止める
  • メールで通知


その他
  • 簡易Webサーバ付きで、状況をWebページで確認できる
  • yumだとRPMforgeから最新版の5.1.1をインストールできる(2010年9月現在)
  • /etc/monit.confはchmodで700にする


参考サイト

2010年9月6日月曜日

Google Maps API (V2)を iPadで使う場合の注意点

各所でiPadには対応していないを書かれているGoogle Maps API V2だが、やってみたら使えた。
以前使ったときには確かに対応していなかったと思うが、最近対応したのだろうか?Change Logにも書かれていないが...。

ただしiPadでは動きが変わる点があったのでメモ。


注意点1
GMarkerに対してdisableDragging()すると、iPadではそのマーカーをクリックしてもclickイベントを感知できないようだ。

対策としてはdisableDragging()しないこと。ドラッグしたいなら、代わりにドラッグ用のGMarkerを表示して、ドラッグが終わったらドラッグ先の場所に元のマーカーを移動して表示する、とすればたいてい間に合うのではないだろうか。


注意点2
こちらはAPIとは関係ないが、Google Mapsで経路検索結果を表示する場合の行き方(乗り物)を指定するパラメータのうち、電車についてのパラメータの値がiPad/iPhoneの場合は特殊なので注意。
詳しくはこちら → GoogleMapの経路検索で、車、電車、徒歩を指定するURL - iRSSの日記

PHPで変数を arrayや objectにキャストする

PHPでは「$after = (array)$before」のようにカッコ付きで型を指定しればデータをキャスト(型変換)できる。
特に、配列の場合とそうでない場合の両方あり得るデータを配列として扱うのに便利。

$arr = (array)$array_or_not;

以下は、配列やobjectにキャストするとどうなるかの実験結果。
//配列にキャスト
var_dump((array)123);         // => array(1) { [0]=>  int(123) }

//配列を配列にキャスト
var_dump((array)array(123));  // => array(1) { [0]=>  int(123) }

//Objectにキャスト
var_dump((object)123);        // => object(stdClass)#1 (1) { ["scalar"]=>  int(123) }

//配列をObjectにキャスト
var_dump((object)array(123)); // => object(stdClass)#1 (1) { [0]=>  int(123) }

//Objectを配列にキャスト
var_dump((array)(object)123); // => array(1) { ["scalar"]=>  int(123) }

2010年8月15日日曜日

CentOS5.5に PostgreSQL8.4をインスール&セットアップする手順

手順のメモ。

古いpostgresがインストールされていたので削除。

yum remove postgresql*
釣られてhttpd(Apache)もアンインストールされたが今回は構わない。


yumでpostgresをインストール。(CentOS5.5からは標準のyumリポジトリにPostgreSQL8.4がある。今までのpostgresと区別するために名前に"84"が付いている。)
yum install postgresql84-server
以下がインストールされる。
  • postgresql84-libs
  • postgresql84
  • postgresql84-server

必要に応じてdevelもインストール。
yum install postgresql84-devel


合わせてLinuxユーザーとして"postgres"が登録されるので、ユーザーを切り替える。
su postgres


初期化。
initdb --encoding=UTF-8 -D /var/lib/pgsql/data/
--encoding=UTF-8は無いとまずい?
--no-locale
は要るのかな?


rootに戻り起動。
/etc/init.d/postgresql start


OS起動時にpostgresが起動するようにしておく。
chkconfig postgresql on

yumのリポジトリに RPMforgeを追加する手順

CentOS5の場合。

wget http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.1-1.el5.rf.i386.rpm

rpm --import http://apt.sw.be/RPM-GPG-KEY.dag.txt

rpm -K rpmforge-release-0.5.1-1.el5.rf.*.rpm

rpm -i rpmforge-release-0.5.1-1.el5.rf.*.rpm


"--enablerepo=rpmforge"を付けた場合のみRPMforgeを使うようにする。
vi /etc/yum.repos.d/rpmforge.repo
下記のように変更する。
enabled=1

enabled=0


参考:AdditionalResources/Repositories/RPMForge - CentOS Wiki

2010年7月25日日曜日

PHPでの camelCaseへの変換と camelCaseからの変換のサンプル

アンダーバーやハイフンやスペースで単語を繋いだ文字列(例 foo_bar_baz)を、camelCaseやPascalCase(Upper Camel Case)に変換したいことがしばしばある。
その他にも先頭だけ大文字にしたかったり、各単語の先頭だけ大文字にしたかったりとか。
PHPにはucfirst()やucwords()があるから意外に楽にできる。



アンダーバー等で単語を繋いだ文字列を、他の形式に変換する

$separator = '_';    //区切り文字
$str = 'foo_bar_baz';  //変換対象の文字列

//先頭だけ大文字にする
echo ucFirst($str); // => Foo_bar_baz

//以降の変換の共通前処理
$ucSpace = ucWords(str_replace($separator, ' ', $str)); // => Foo Bar Baz

//各単語の先頭が大文字にする
echo str_replace(' ', $separator, $ucSpace); // => Foo_Bar_Baz

//PascalCase(先頭は大文字)にする
echo str_replace(' ', '', $ucSpace); // => FooBarBaz

//camelCase(先頭は小文字)にする ※要PHP5.3+
echo lcFirst(str_replace(' ', '', $ucSpace)); // => fooBarBaz
スペース区切りにすればucWords()が使えるのがミソ。もともと使いたい区切り文字がスペースならもっと楽。

lcfirst()のないPHP5.3未満でcamelCaseにするには少し面倒かも。
この方法が一番手軽そう(未検証)→ PHP: lcfirst - Manual



camelCaseから区切り文字で繋いだ形式に変換する
$separator = '_';    //区切り文字
$camel = 'fooBarBaz';
echo strToLower(preg_replace('/([a-z])([A-Z])/', "$1$separator$2", $camel)); // => foo_bar_baz
PascalCaseからTitle Case(スペース区切りで先頭だけ大文字の形式)への変換なら、strToLower()は要らない。



ハイフン区切りの文字列・先頭が大文字のスペース区切りの文字列・PascalCaseの文字列の相互変換ならこんな感じか。
function convertCase($str, $case) {
    switch ($case) {
        case 'hyphen':    // foo-bar-baz
            $str = preg_replace('/([a-z])([A-Z])/', "$1-$2", $str);
            return str_replace(' ', '-', strToLower($str));
        case 'normal':    // Foo bar baz
            $str = preg_replace('/([a-z])([A-Z])/', "$1 $2", $str);
            return str_replace('-', ' ', ucFirst(strToLower($str)));
        case 'pascal':    // FooBarBaz
            return str_replace(' ', '', ucWords(str_replace('-', ' ', $str)));
    }
}
正規表現だけでもいろいろできちゃいそうだけど、(正規表現を駆使出来ていない自分のような人には)見辛くなるのでstr_replace()を使った。(コードが横に長くなるし。)

2010年7月5日月曜日

jQuery UIの Datepickerで日本語のカレンダーを表示する方法

(2010/07/05追記:年月選択のオプションと、その見た目の調整のCSSを追加した。)
(2013/05/01変更:CSSがmin対応したので変更した。)

必要なJavaScriptとCSSは、全てGoogleがホスティングしてくれてた。
(2010/10/12追記:日本の祝日を表示するGCalendar HolidaysだけはGoogleはホスティングしていない。)


サンプルコード

<!DOCTYPE html>
<html lang="ja">
<head>
<title>Datepicker</title>

<!-- jQuery UIのCSSファイルの読み込み -->
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/flick/jquery-ui.min.css" />

<!-- 見た目の調整 -->
<style>
.ui-datepicker td span, .ui-datepicker td a {
    text-align: center;    /* 日付はセンタリングの方が好き */
}
/* 2011/4/25 削除 (土日の背景色はGClendar Holidaysが付けてくれる)
.ui-datepicker-week-end .ui-state-default {    / * 土日の背景を変える * /
    background-image: none;
    background-color: #b4ebfa;
}
*/
.ui-datepicker select.ui-datepicker-year, .ui-datepicker select.ui-datepicker-month {
    width: auto;    /* そのままだと改行してしまう */
}
.ui-datepicker select.ui-datepicker-month {
    margin-left: 1em;    /* ちょっと離すほうが好き */
}
</style>

</head>
<body>

<input id="test" type="text" />


<!-- JavaScriptファイルの読み込み -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>

<!-- 日本語カレンダーを表示するにはこれも要る -->
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/i18n/jquery.ui.datepicker-ja.min.js"></script>

<!-- こちらなら日本だけでなく全てのローカライズができるが、ファイルサイズが大きい
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/i18n/jquery-ui-i18n.min.js"></script>
-->

<!-- 2010/10/12追記:日本の祝日も表示 -->
<script src="gcalendar-holidays.js"></script>

<script>
$(function() {
    //テキストボックスにカレンダーをバインドする(パラメータは必要に応じて)
    $("#test").datepicker({
        //regional: "ja",    //日本語化 (2011/4/25 削除、要らなくなったみたい)
        showButtonPanel: true,    //「今日」「閉じる」ボタンを表示する
        firstDay: 1,    //週の先頭を月曜日にする(デフォルトは日曜日)
      
        //年月をドロップダウンリストから選択できるようにする場合
        changeYear: true,
        changeMonth: true,
      
        //選択可能な日付の範囲を限定する場合(月は0~11)
        minDate: new Date(2010, 6 - 1, 16),
        maxDate: new Date(2010, 8 - 1, 15)
    });
});
</script>

</body>
</html>

jQuery UIのテーマ(外観のデザイン)はjQuery UI - ThemeRollerで見られる。


Datepickerのローカライズ用ファイルは、Google AJAX Libraries APIjQuery UI on Google Codeと同じディレクトリ構成だったので見つけられた。(余談だがi18nディレクトリには今のところDatepickerのローカライズ用ファイルしか無いようだ。)
Google Codeの方には最小化されたファイル(xxx.min.js)は無かったが、AJAX Libraries APIの方にはあった。(ローカライズ用JSファイルは最小化してもそれほどファイルサイズが小さくならないけど。)CSSはminは無いようだ。
ちなみにjQuery UI本家のDatepickerのデモでもGoogle AJAX Libraries API(きちんとmin.jsの方)のを使っていた。


Google AJAX Libraries APIを使う場合にバージョンアップで突如使えなくなるのを回避したいなら、jQueryとjQuery UIのバージョンはリビジョンまでしっかり指定しておいた方が無難。


(2010/08/19追記)
GCalendar Holidaysを使えば、Datepickerのカレンダー上に日本の祝日を表示できる。(2011/4/25 さらに追記:土日の背景色も表示してくれる。)
サンプル:GCalendar HolidaysでjQuery UI Datepickerに祝日を表示するのサンプル - ゼロと無限の間に
(追記終わり)


参考

PHP 5.3の地味な新機能 「ネストされたException」

PHP5.3から、Exceptionのコンストラクタの第3引数に別のExceptionを渡せるようになったらしい。


例えばこんな感じで。

<?php throw new Exception('Ex1', 0, new Exception('Ex2')) ?>

エラー出力はこんな感じになる。第3引数として渡された方が先に出力され、親の方は「Next exception」として出力される。
PHP Fatal error:  Uncaught exception 'Exception' with message 'Ex2' in /xxx/exception.php:1
Stack trace:
#0 {main}

Next exception 'Exception' with message 'Ex1' in /xxx/exception.php:1
Stack trace:
#0 {main}
  thrown in /xxx/exception.php on line 1




もういっちょいってみるか?
<?php throw new Exception('Ex1', 0, new Exception('Ex2', 0, new Exception('Ex3'))) ?>

結果。
Fatal error: Uncaught exception 'Exception' with message 'Ex3' in /xxx/exception.php:1
Stack trace:
#0 {main}

Next exception 'Exception' with message 'Ex2' in /xxx/exception.php:1
Stack trace:
#0 {main}

Next exception 'Exception' with message 'Ex1' in /xxx/exception.php:1
Stack trace:
#0 {main}
  thrown in /xxx/exception.php on line 1


便利そうだが、今のところ使いどころを思いつかない。


参考:PHP 5.3で追加された例外のうんたらかんたら - ゆっくり*ゆっくり

2010年6月23日水曜日

検索サイトのリンクの色の比較

最適 なテキストリンクの色は? | ウェブ力学に触発されて、大手検索エンジンの検索結果ページのリンクの色を調べてみた。


調査結果


GoogleYahoo! JAPANYahoo!Bing
a#1111CC#0000DE#0000DE#0033CC
a:visited#551A8B#941D55#551A8B#663399
a:active#CC1111#663399#0000DE指定なし
a:hover指定なし#CC3434指定なし指定なし

※Yahoo! JAPANのvisitedは、検索結果のリンクをクリックした後の色。再度検索すると、同じ検索結果でもvisitedにならない(また青色に戻る)。


所感
  • Yahooは本家と日本で違う。
  • hoverの指定をしないのが主流なのが意外だった。
  • activeも指定しない方向で?
  • Bingが一番すっきりしていて好き。



また、こんな調査結果もあった。
自分が調べたのとちょっと違う。検索サイトも細かい改良をし続けているということかな?

Google Appsのカレンダーを携帯で閲覧する方法

下記のようなURLにアクセスすると、携帯用のGoogleカレンダーを閲覧できる。

https://www.google.com/calendar/hosted/<Google Appsのドメイン>/m


このURLはPCからでも接続できる。
しかし携帯からアクセスすると、なぜかhttpになる。(httpsだとauでUTF-8が使えないから?)


ちなみに携帯で下記URLにアクセスすると、サーバ証明書が不正だといって接続を拒否された。
https://calendar.google.com/a/<Google Appsのドメイン>/m
このURLは昔使ってたみたいで、未だにGoogleの公式サイトを含めてこのURLが書いてあるところが多い。
PCでこのURLにアクセスすると、上のURLの方にリダイレクトされる。


また、携帯版のカレンダーでは見たい日付を指定できないので、遠い日付を見たい場合には「前」あるいは「次」リンクを連打する羽目になる。
Google Calendar Mobile Gatewayを使うしかないのか。

2010年6月15日火曜日

PHPの json_encode()で配列になるかハッシュになるか

json_encode()でPHPの配列をJSONにする場合に、PHPの配列の内容によってJSONの配列(Array)になるかハッシュ(JSONの場合KEYが文字列のプロパティの集合)になるかを調べてみた。


PHPの連想配列(KEYあり)の場合

$arr = array('foo' => 'a', 'bar' => 'b', 'baz' => 'c');
echo json_encode($arr);
// => {"foo":"a","bar":"b","baz":"c"}
→JSONのハッシュになった。


PHPの配列(KEY指定なし=ゼロから始まる連番)の場合
$arr = array('a', 'b', 'c');
echo json_encode($arr);
// => ["a","b","c"]
→JSONの配列になった。


PHPの配列を、json_encode()のオプション指定で強制的にハッシュにした場合
$arr = array('a', 'b', 'c');
echo json_encode($arr, JSON_FORCE_OBJECT);
// => {"0":"a","1":"b","2":"c"}
→JSONのハッシュになった。


PHPの連想配列で、一部だけKEY指定なしの場合
$arr = array('foo' => 'a', 'b', 'baz' => 'c');
echo json_encode($arr);
// => {"foo":"a","0":"b","baz":"c"}
→JSONのハッシュになった。


PHPの配列から最初の要素を消した場合
$arr = array('a', 'b', 'c');
unset($arr[0]);
echo json_encode($arr);
// => {"1":"b","2":"c"}
→JSONのハッシュになった。


PHPの配列から最初 途中の要素を消した場合
$arr = array('a', 'b', 'c');
unset($arr[1]);
echo json_encode($arr);
// => {"0":"a","2":"c"}
→JSONのハッシュになった。


PHPの配列から最後の要素を消した場合
$arr = array('a', 'b', 'c');
unset($arr[2]);
echo json_encode($arr);
// => ["a","b"]
→JSONの配列になった!


PHPの連想配列でKEYをゼロから始まる連番で指定した場合
$arr = array(0 => 'a', 1 => 'b', 2 => 'c');
echo json_encode($arr);
// => ["a","b","c"]
→JSONの配列になった。


PHPの連想配列でKEYを数値だけど連番じゃないものにした場合
$arr = array(0 => 'a', 1 => 'b', 4 => 'c');
echo json_encode($arr);
// => {"0":"a","1":"b","4":"c"}
→JSONのハッシュになった。



結論
json_encode()により配列(Array)になるのは、PHPの(連想)配列のKEYがゼロから始まる連番の場合のみ

Google AJAX Libraries APIのブラウザキャッシュ期間

Google AJAX Libraries APIではバージョンの指定の際にマイナーバージョンやリビジョンを省略できる。

例えばYahoo! User Interface Libraryには2.8.1というバージョンがあるので、下記のようにバージョンを指定できる。

  • 2 → バージョン2系の中の最新版をロードする
  • 2.8 → バージョン2.8系の中の最新版をロードする
  • 2.8.1 → バージョン2.8.1系の中の最新版をロードする


で、それぞれの場合のHTTP Headerによるキャッシュ制御を調べてみる。
yuiloader-min.jsを静的に読み込んだ場合で調べてみた。

指定方法max-ageExpiresEtag
メジャーバージョン(2)1時間1時間後なし
マイナーバージョン(2.8)1時間1時間後なし
リビジョン(2.8.1)1年1年後なし

YUIは「2.8.1.1」のような2.8.1系の新しいバージョンが出ることはない(※)ので、リビジョンまで指定した場合はキャッシュ期間を1年にしている。
それ以外は1時間。ちょっと短いせめて1日くらいでも良さそうな気がするが。

※これまでのバージョンの付け方を見る限りはない。もしあったとしたら2.8.1-1のようにドット以外で繋ぐことにより回避するかもね。

PHPで ob_start()後に exitするとどうなるか

PHPでob_start()でコールバック関数を指定した場合、スクリプトを終了した後にコールバック関数が呼ばれる。

ではスクリプトの途中でexitしたらどうなるかというと、exit後にコールバック関数が呼ばれた。

<?php
function callback($buf) {
    return $buf . ' callback'; //呼ばれる
}

ob_start('callback');

echo 'foo';

exit;

echo 'bar'; //呼ばれない

// => foo callback


コールバック関数を指定せずに、exit後にob_get_clean()等でバッファを処理しようとした場合は、(当然ながら)exit後の処理は実行されない。
<?php
ob_start();

echo 'foo';

exit;

echo ob_get_clean();

echo 'bar'; //呼ばれない

// => foo

2010年6月14日月曜日

PHPを mod_cache (mod_disk_cache)でキャッシュする

Apacheのmod_cacheとmod_disk_cacheを使って、PHPで生成したHTMLをキャッシュする方法のメモ。


Apacheの設定では、LoadModuleでmod_cacheとmod_disk_cacheを有効にする。
そして下記のようにキャッシュの設定をする。

CacheRoot /path/to/cache/dir
#キャッシュ方法と、キャッシュを有効にするURLの先頭部分
CacheEnable disk /test
#上記URLのうち、キャッシュを無効にするURL
CacheDisable /test/not_cache
CacheDirLevels 4
CacheDirLength 5
#クライアントの挙動に関わらずキャッシュを有効にする
CacheIgnoreCacheControl On


PHP側では下記のようにHTTP Response HeaderのLast-ModifiedとExpiresをセットする。(max-ageもセットした方がよい?)
$now = time();
$maxAge = 60;
header('Last-Modified: ' . gmdate('D, d M Y H:i:s T', $now));
header('Expires: ' . gmdate('D, d M Y H:i:s T', $now + $maxAge));
//header("Cache-Control: max-age=$maxAge");

これで60秒間、サーバサイドでもキャッシュされる。
同一クライアントからのアクセスなら、60秒間はクライアントキャッシュが有効。それでもGETしようとしてきた場合(Firefoxで更新ボタンをクリックした場合等)はmod_cacheが304を返してくれる。



PHPでHTTP Response Headerを指定しない場合は、Apacheのキャッシュ設定に下記を追加する。
CacheIgnoreNoLastMod On
CacheDefaultExpire 86400
#キャッシュから1秒以上過ぎたら1日キャッシュを有効にする場合はこんな値で
CacheLastModifiedFactor 86400
CacheMaxExpire 86400

これでHTTP Response Headerを指定しない場合でもサーバサイドのキャッシュが有効になったが、クライアントキャッシュは有効にならないのが残念。
気を利かせて適切なHTTP Response Headerをセットしてくれればいいのに。



キャッシュファイルは定期的にhtcachecleanで掃除する。
(空のディレクトリがうまく削除されない?)



参考

システム開発で使うオンラインの日本語マニュアル



意外とマニュアル内検索が無かったり、あっても検索しづらかったりすることが少なくない。
また、普通にGoogle検索から探そうとすると古いマニュアルばかりヒットすることも(Postgresとか)。
素直に英語のマニュアルで調べればいいんだろうけど...

Google Reader plus Hatenaで「リスト表示」でもコメントを表示する方法

Firefox用GreasemonkeyのGoogle Reader plus Hatenaは、Googleリーダーに はてなブックマークのブックマーク数やリンクが付けてくれる便利なスクリプト。
Googleリーダーでの表示方法が「全文表示」の場合は、はてなブックマークのコメントを取得して記事の下に表示するという機能もある。
しかし、表示方法が「リスト表示」の場合は、このコメント表示機能が動かない。

下記に「リスト表示」でも動かす方法が書いてあったが、自分の環境ではこの方法では動かなかった。(GoogleリーダーのHTML構成が変わった?)
googleリーダー内ではてなブックマークのコメントを参照したいです。 Google Reader plus Hatenaというグリモン... - 人力検索はてな


そこで、自分の環境で「リスト表示」でも はてなブックマークを表示する方法のメモ。

  • 172行目を下記のように変更

    //var entryURL = findNode( eventTarget, 'ancestor::div[@class=...

    var entryURL = findNode( eventTarget, 'ancestor::div[@id="current-entry"] //a[@class="entry-title-link"]/@href' ) ;
  • 200行目を下記のように変更

    //eval("(" + x.responseText + ")");

    eval(x.responseText);


全文表示では動かなくなるかもしれないが、リスト表示しか使わないのでこれでいいや。

2010年6月10日木曜日

Zend Frameworkと PEARの命名規約に相違点

Zend Frameworkの命名規約とPEARの命名規約。両方ともJavaの命名規約を元にしていると思われる。変数でアンダーバーを使わないところとか。($foo_barではなく$fooBarとキャメルケースにする。)

Zend FrameworkとPEARの命名規約はかなり似てるが、細部まで見ると少し違う。
相違点を洗い出してみた。


Zend Framework
PEAR
アルファベットの略語先頭だけ大文字にする
例:Zend_Pdf
略語全体を大文字にする
例:HTML_Upload_Error
抽象クラスクラス名の後ろに"Abstract"を付ける
例:FooAbstract
言及なし
インターフェイスクラス名の後ろに"Interface"を付ける
例:FooInterface
言及なし
protectedアンダーバーで始める
例:$_foo
アンダーバーで始めない
例:$foo


Zend Frameworkの方がいいと思う。


参考:
Zend Framework: Documentation: 命名規約 - Zend Framework Manual
Manual :: 命名規約 (← PEAR)

PHPの DateIntervalクラスで経過日数を調べる場合の注意点

PHP5.3で新しく追加されたDateIntervalクラス。
一見便利そうだが、DateTimeクラスやstrToTime()のように日付等の繰り上がりを計算してくれないので注意が必要。
しかも、オブジェクトの生成方法により内部的なデータの持ち方が違う。


DateTimeクラスのdiff()(またはdate_diff())でDateIntervalオブジェクトを生成した場合、1ヶ月以上の日数は「月」に繰り上がる。
総日数は format('%a') で得られる。

$d1 = new DateTime('2010-01-01 01:01');
$d2 = new DateTime('2010-02-02 02:02');
$interval = $d2->diff($d1);

echo $interval->format('%m') . 'ヶ月と' . $interval->format('%d') . '日<br />';
// => 1ヶ月と1日

echo '全部で' . $interval->format('%a') . '日';
// => 全部で32日


でもDateIntervalクラスのコンストラクタで「1ヶ月と1日」としてDateIntervalオブジェクトを生成した場合、総日数は format('%d') でも format('%a') でも得られない。
$interval = new DateInterval('P1M1D');

echo $interval->format('%m') . 'ヶ月と' . $interval->format('%d') . '日<br />';
// => 1ヶ月と1日

echo '全部で' . $interval->format('%a') . '日';
// => 全部で0日


DateIntervalクラスのコンストラクタで「32日」としてDateIntervalオブジェクトを生成した場合、総日数は format('%d') で得られる。format('%a') は使えない。
$interval = new DateInterval('P32D');

echo $interval->format('%m') . 'ヶ月と' . $interval->format('%d') . '日<br />';
// => 0ヶ月と32日

echo '全部で' . $interval->format('%a') . '日';
// => 全部で0日


format()する際には、DateIntervalオブジェクトをどうやって作ったかを意識する必要がある。

DateInterval::format()のマニュアルにも書いてあるとおり、これは仕様なのだろう。(月により1ヶ月の日数が違うため、コンストラクタでnヶ月と指定された場合にその総日数は不定のため。)

DNS Rebinding(リバインディング)についての調査メモ

DNS Rebindingは質(たち)が悪いらしい

【White Hat Security調査】2010年に最も警戒すべき脅威は「DNSリバインディング」 : セキュリティ・マネジメント - Computerworld.jp
(補足)はてなブックマーク - ockeghemのブックマーク - 2010年3月19日



DNS Rebindingについてのわかり易い説明

DNS Rebinding | 鳩丸ぐろっさり (用語集)



DNS Rebindingを悪用する具体例

セキュリティ情報 - iモードIDを用いた「かんたんログイン」のDNS Rebinding脆弱性
ケータイtwitter(twtr.jp)においてDNS Rebinding攻撃に対する脆弱性を発見・通報し、即座に修正された - 徳丸浩の日記

これらの例ではLANではなく、携帯の「かんたんログイン」との合わせ技により脆弱性を突いている。



簡易テスト

「かんたんログイン」DNSリバインディング耐性のチェック方法 - 自分でできる - HASHコンサルティング徳丸浩の日記



サーバ側での対策




参考
untitled - Powered by Google ドキュメント

2010年6月7日月曜日

PHPの バージョン5.xで追加された便利なクラス

PHPの5.xで組み込みオブジェクトとして提供される便利なクラス。
たまに古いPHPを使うときに、どのバージョンで何を使えるか/使えないか分からなくなるのでメモ。

バージョン追加された便利なクラス
PHP 5.0.1SimpleXML
PHP 5.1.0PDO
PHP 5.2.0DateTime, ZipArchive, JSON関数(※)

※JSON関数はクラスではないけど



PHP5.3では下記のクラスが便利そうだけど、まだきちんと使ったことはない
  • DateInterval (DateTimeの加減算等に使える)
  • DatePeriod (日時を指定した範囲でループできる)
    • 例1:7/1から7/7までの日付を出力

      $dp = new DatePeriod(new DateTime('2010-07-01'), new DateInterval('P1D'), 6);

      foreach ($dp as $dt) {
          echo $dt->format('Y/m/d') . '<br />';
      }
    • 例2:同じく、7/1から7/7までの日付を出力

      $dp = new DatePeriod(
          new DateTime('2010-07-01'),
          new DateInterval('P1D'),
          new DateTime('2010-07-08')
      );

      foreach ($dp as $dt) {
          echo $dt->format('Y/m/d') . '<br />';
      }
  • FilesystemIterator (指定したディレクトリにあるファイルをループ)



PHP5.2.0、5.3.0で追加されたクラスは、PHPマニュアルにまとめページがある。

CSSによる背景色グラデーションのブラウザごとの書き方

例えば、上から下に白から青のグラデーションを表示したい場合はこう書く。(省略可能なパラメータは省略した。)

/* IE */
filter: progid:DXImageTransform.Microsoft.Gradient(StartColorStr=#ffffffff, EndColorStr=#ff0000ff);

/* IE8 */
-ms-filter: "progid:DXImageTransform.Microsoft.Gradient(StartColorStr=#ffffffff, EndColorStr=#ff0000ff)";

/* Firefox */
background: -moz-linear-gradient(white, blue);

/* Chrome, Safari */
background: -webkit-gradient(linear, left top, left bottom, from(white), to(blue));

IE8は右辺をクォートで囲う必要があるので注意。

IE以外は、詳細な指定をすれば複数の濃淡を指定できたり球状の効果を表現できたりと色々できる。

Operaは未対応らしい。


参考
IE:Gradient - filter,フィルタ
Firefox:-moz-linear-gradient - MDC
Chrome, Safari:CSSでグラデーションを表現する - builder by ZDNet Japan

Googleドキュメントで他のユーザーを招待する場合のセキュリティ

Googleドキュメント(Google Docs)で他のユーザーを招待すると、招待用のURLが記載されたメールが送られる。
実はこのURLにアクセスすると、招待されたユーザー以外でもそのページにアクセスすることができる

この件については下記が詳しい。

高木浩光@自宅の日記 - Googleドキュメントの「招待メール」の危険

上記記事が書かれた時からの変更点として、現在は招待用URLからGoogleドキュメントにアクセスする前にGoogleアカウントでのログインが求められるため、Googleアカウントを持っていないユーザーはアクセスできなくなった。

しかし、招待用URLさえ分かれば、Googleアカウントを持っているユーザーなら誰でもアクセスできてしまうことに変わりはない。

(参考:そのドキュメントに誰も招待していなければ、招待用URL自体が作成されないので他のユーザーはアクセスできない。)



以上がデフォルト設定の場合の話。

Googleドキュメントではオプション設定により、アクセスできるユーザーを招待した人だけに限定することができる。

共有ボタンから「他の人と共有」ダイアログを表示させて、下記のように「権限オプション」タブを見ると、「招待状の転送を許可する」というチェックボックスがある。



デフォルトではチェックが付いているので、転送してもらった人でもアクセス可能、つまりURLさえ分かればアクセス可能になる。
このチェックを外して保存すれば、アクセスできるのは招待されたユーザーのみになる



この設定はなかなか分かりにくいので、Googleさんは「許可しない」をデフォルトにした方がいいと思う。あるいは、ユーザーごとの設定でデフォルトを決められるようにするか。

ブログ アーカイブ

tags