- 投稿: 2011年02月17日 22:34
- 更新: 2011年02月17日 22:34
- ソフトウェア
イサムの開発にあたって,いくつかの新しいテクニックを用いたので,新旧あわせて使ったテクニックを紹介したいと思います.
mod_rewriteでGETパラメータを変換
例えば,以下のようなURLを考えます.
http://4403.biz/ISAM/organization/NEC/
なんとなくパーマリンクっぽくて素敵ですよね.でも,この実体は以下のように処理したいと考えます.
http://4403.biz/ISAM/hoge.php?mode=organization&query=NEC
この変換をmod_rewriteで実現します.まぁ,Wordpressとかで使われている常套句ですね.mod_rewriteが有効な状態で,.htaccessに以下のように書きます.
RewriteEngine on
RewriteBase /ISAM/
RewriteRule "^(.*)/(.*)/$" "hoge.php?mode=$1&query=$2" [L]
簡単ね!ご存じだとは思いますが,これにGETパラメータがさらにくっつくような状況下では,QSAフラグも付けましょう.
hoge.phpでは受け取ったGETパラメータによって処理を振り分けたらいいと思います.これで実体を隠蔽しつつ,パーマリンクっぽいURLも提供できて,なんだかすごくいい感じです.クールURI!
mod_rewriteのBフラグ
上記の設定の後に,以下のようなアクセスを想定しましょう.
http://4403.biz/ISAM/organization/KDDI R&D Labs./
なんとなく上手くいかなさそうな気配がぷんぷんしますよね?実際にやってみると,このように展開されます.
http://4403.biz/ISAM/hoge.php?mode=organization&query=KDDI R&D_Labs_=
なんだか変なことになっている.紐解きましょう.GETパラメータがどうなっているかというと以下の通りです.
mode=organization
query=KDDI R
D_Labs_=
おい!って話ですね.問題点はR&Dの&をGETパラメータの接続詞と解釈してしまっています.解釈してしまっていますというか,それで正しいわけですが・・・.単純な解決策はURLエンコードです.しかし,そのためには,以下のようなアクセスを想定することになります.
http://4403.biz/ISAM/organization/KDDI%20R%26D%20Labs%2e/
こんなの恥ずかしくて見せられない!ということで,これをmod_rewrite中に実現したいわけですね.で,調べてみるとあるんですよ,これが.apache2.2.6以降らしいですが,Bフラグというものがあります.以下,引用.
- ‘
B
‘ (escape backreferences)- Apache has to unescape URLs before mapping them, so backreferences will be unescaped at the time they are applied. Using the B flag, non-alphanumeric characters in backreferences will be escaped. For example, consider the rule:
RewriteRule ^(.*)$ index.php?show=$1
This will map/C++
toindex.php?show=/C++
. But it will also map/C%2b%2b
toindex.php?show=/C++
, because the%2b
has been unescaped. With the B flag, it will instead map toindex.php?show=/C%2b%2b
.
This escaping is particularly necessary in a proxy situation, when the backend may break if presented with an unescaped URL.
簡単ね!というわけで,先ほどのRewriteRuleにBフラグを追加すると,こんなアクセスが来ても,
http://4403.biz/ISAM/organization/KDDI R&D Labs./
こんな風に渡されるので,
http://4403.biz/ISAM/hoge.php?mode=organization&query=KDDI%20R%26D%20Labs%2e
hoge.php側では$_GET[‘query’]をurldecodeしておけばいいですね.いい時代だね~.
memcachedの導入
インクリメンタルサーチでゴリゴリ検索させています.基本的にかなりの力業実装です.ですので,負荷を減らすためにキャッシュは重要になります.当初はMySQLのキャッシュ機能とAPCに丸投げしていたのですが,DBの更新が無ければ結果は不変なので,まるっとキャッシュしてしまえばいいのではないかと思ったので,memcachedしました.初挑戦です.
そもそもmemcachedとは何かといえば,以下のようなものだそうです.
Free & open source, high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load.
ということで目的にピッタリです.で.基本的な使い方を確認しましょう.PHPではpecl::memcacheを使うのがいいのかな?似たものにpecl::memcachedもあります.よくわかりません.今回はmemcacheを使います.基本的な使い方は以下の通りです.
$mem = new Memcache; $mem->addServer('localhost', 11211); $val = $mem->get($key); if(!$val) { //$valを作る作業 $mem->add($key, $val, MEMCACHE_COMPRESSED, 3600); } $mem->close();
簡単ですね.これを応用して,イサムをキャッシュしまくります.方針としては,$keyをSQLクエリにして,$valをHTML出力文字列としています.つまりは,SQLクエリをキーにしてページフルキャッシュとほぼ同等です.これでキャッシュにヒットすればサックサクのはずです.
これをよくよく考えると,実行時間命なシステムでDBへの書き込みや更新がボトルネックになっている場合,とりまmemcachedにはき出しておいて,別プロセスで非同期にmemcachedから取り出してDBに格納するとかしてレイテンシを隠蔽できそう.そんなクリティカルなシステムを作ったことないですけどね.
エスケープとか
エスケープも別に珍しいことはしてなくて,strip_tagsやらmysql_escape_stringやらhtmlentitiesやらを使ってます.「エスケープは出力時に」という基本に忠実です.SQL文の構築はプレースホルダーを用いているので,そんなに変なことは起きないはずだと信じてます.攻撃しないで!
PHPの小ネタ
PHPはHTMLの中に直接スクリプトが書けるという実に変態な言語なので,様々な変態テクニックが駆使可能です.例えば,if文の途中でphp終了タグでぶった切って,HTMLを出力(というかそのまま表示)して,php開始タグで再びif文に復帰するとかいう常識的に考えられないような変態スーパーテクニックが利用可能です.可読性?なにそれ?誰が読むの?
それはそれとして,多少便利なものとしては,includeを用いたページ分割です.include命令によって別のphpファイルを読み込む(C言語の#includeのように)ことができるので,共通であるヘッダ部とフッタ部を別ファイルに分割することで,コード修正時の修正範囲を限定的にすることができます.ちなみに,これはHTMLヘッダ部でもできますので,かなり応用が利きますよ.
スーパーテクではありませんが,jQueryと組み合わせてajaxでインクリメンタルサーチやサジェストを実現しています.
- Newer: はじめての整体体験
- Older: 平成22年度第2学期の成績