特定のサイトで文字コードを変更する
.htaccessで以下のように設定すると特定のサイトの文字コード設定を変更できる。(PHP5の場合)
php_value default_charset "Shift-JIS"
1985年ラスマス・ラードフによって書かれたPHP Hypertext Preprocessorについて。個人向け言語だったPHPがこれほどまでに発展したのはZendの多大なる貢献によるものだろう。
.htaccessで以下のように設定すると特定のサイトの文字コード設定を変更できる。(PHP5の場合)
php_value default_charset "Shift-JIS"
ソースコードを変更せずにPHPの動作を高速化することが出来るアクセラレーターがあるようです。検証結果がcubic9.comさんにありますので、掲載しておきます。なお、MMCacheはeAcceleratorに変更になっています。
今度試して検証結果を報告したいと思います。
PHPはコードの書き方にもよるけれども、結構メモリを食うことがある。しかし、どれくらい食っているかはなかなかわかりづらい。そこで、こんな関数を使ってみてはどうだろうか?
どのようなDBであるかを意識することが必要なくなる抽象レイヤライブラリ「ADOdb」の利点について。名前の由来はMicrosoftが提唱していたADO(ActiveX Data Objects)にちなんでいる??
・プレースホルダを利用することでプログラマはSQL injectionに対する心配をしなくても良い
・DB依存しなくなるため、DBの変更が容易(アプリケーションとDBの結合度を下げる)
・キャッシュ機構を利用することができ、よく発行されるクエリに対して高速に応答することができるようになる
具体的な例
詳細なガイド
ブログシステムを作ると必ずといっていいほどトラックバックスパムに悩まされることが多いのではないだろうか?そこでトラックバックスパムを制限する方法について今日は調べてみた。
スパムホストかどうかをチェックするためのDBがDNSBLというものだそうだが、それを利用できるモジュールがPEARにあったので紹介する。
JANコードには13桁のコードと短縮の8桁コードが存在するが、いずれもバーコードの読み込みエラーを防ぐためにチェックデジットが存在する。正しいJANコードかどうかを判定する正規表現をPHPで実装してみたのが次のコード。
function verifyCheckDigit($jan_code){
return (preg_match('/^(?:(\d)(\d)(\d)(\d)(\d))?(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)$/', $jan_code, $arr_arg) && (
(10 -
(($arr_arg[2] + $arr_arg[4] + $arr_arg[6] + $arr_arg[8] + $arr_arg[10] + $arr_arg[12]) * 3 +
$arr_arg[1] + $arr_arg[3] + $arr_arg[5] + $arr_arg[7] + $arr_arg[9] + $arr_arg[11]) % 10) % 10 == $arr_arg[13]
));
}
Apacheのdefault_charset設定がされている場合、クライアントに通知される文字コードが設定によってしまう(当たり前だが)。default_charsetで配信したくない内容(たとえばEUCでコンテンツを配信しているが、一部はXML配信したい場合など)は以下の方法で変更できる。
header("Content-Type: text/html; charset=UTF-8");
オレンジニュースを見ていたら、PHPにも致命的なエラーに対するハンドリングする方法ってのが紹介されていました。さすがに文法エラーまではハンドリングしてくれない(もちろん実行できないわけですから)ですが・・・。サイト内のページが多いと実はエラーで落ちているのに気づかないっていうケース(これもWebサーバーのログをちゃんと見ていれば問題ないはずですが)もありますから、結構活躍してくれそうです。
今日、とある理由でZend Japanの社長とお会いすることができました。Zend Japanのページを見てみると、コード標準が存在していました。社内でもコード標準があるのですが、制定するのにずいぶん苦労しました。こういう形でガイドラインがあれば非常に参考になりますね。
http://www.zend.co.jp/tech/index.php
array('a', 'b', 'c', 'd')のような1次元配列をarray('a'=>array('b'=>array('c'=>array('d'))))のような多次元配列に変換するにはどのようなアルゴリズムを用いればよいだろうか?
おそらくこれを実現するのは、ポインタを使わざるを得ないだろうということで以下のようなコードを実装してみた。
function _makeTreeStructure($arr_level, $value){
$arr_data = array();
$p = &$arr_data;
for ($i = 0; $i < count($arr_level); $i++){
$p = array($arr_level[$i] =>
($i == count($arr_level) - 1) ? $value : '');
$p = &$p[$arr_level[$i]];
}
return $arr_data;
}
実行コード
var_dump(makeTreeStructure(array('a', 'b', 'd', 'a', 'b', 'd'), 3));
結果は以下の通り
array(1) {
["a"]=>
array(1) {
["b"]=>
&array(1) {
["d"]=>
&array(1) {
["a"]=>
&array(1) {
["b"]=>
&array(1) {
["d"]=>
int(3)
}
}
}
}
}
}
fgetcsv関数はVer.4→5の間で仕様変更があり、ロケール設定を考慮するようになったので、場合によっては文字化けしたり、\""に囲まれた改行を正しく処理できなかったりする。その場合には、
setlocale(LC_ALL, 'ja_JP.eucJP');
Perlでマルチバイトマッチングを行うためには、jcode.plで $a =~ /[亜-煕]/ のようにするとマッチングできる。また、Perl 5.6からはUTF-8にてマッチングが可能だ。
PHPでもmb_eregという関数が用意されており、こちらでマッチングできるのだが、perg_match関数のようなPerl互換の強力な正規表現は用意されていない。
すべての漢字を取り出す正規表現としてコードが公開されているが、もうすこし効率の良いマッチングがPHPでもできれば柔軟な正規表現をかけるのだが。
ところで、HotPHPPER Feedには結構面白いブログのフィードが投稿されているようなので、今後はチェックしていきたい。
mb_send_mail関数がFALSEを返すという症状に遭遇した。error_reporting(E_ALL);に設定してもエラーメッセージは一切出力されないので、問題解決に苦労した。
/var/log/maillogには何も出力されていなかったので、おそらくPHPがSMTPサーバーにメールを渡せていないのだろうと考え、Googleで調べてみたところ際コンパイルしてみたほうが良いとのことで、際コンパイルをしてみたらうまくいった。
おそらくコンパイル時に/usr/sbin/sendmailを認識できないとmail関数は利用できないということのようだ(まぁ、あたりまえか)。
それにしても、エラーが出ないとトラブルシューティングしにくいですね。
以下のプログラムを実行してみるとおもしろい結果が分かる。PHPはセッションIDを知っているにもかかわらずsession_start関数が呼ばれなければ、session_idを返さないのだ。
<?php
var_dump(session_id());
var_dump($_COOKIE['PHPSESSID']);
session_start();
var_dump(session_id());
?>
配列の結合関数array_mergeと+演算子には挙動の違いがあるので注意したほうが良い。
<?=var_dump(array('A' => 'a', 'B' => 'b') + array('A' => 'c', 'D' => 'd')); ?>
<?=var_dump(array_merge(array('A' => 'a', 'B' => 'b'), array('A' => 'c', 'D' => 'd'))); ?>
array(3) {
["A"]=>
string(1) "a"
["B"]=>
string(1) "b"
["D"]=>
string(1) "d"
}
array(3) {
["A"]=>
string(1) "c"
["B"]=>
string(1) "b"
["D"]=>
string(1) "d"
}
array(4) {
["A"]=>
string(1) "a"
["B"]=>
string(1) "b"
["C"]=>
string(1) "c"
["D"]=>
string(1) "d"
}
array(4) {
["A"]=>
string(1) "a"
["B"]=>
string(1) "b"
["C"]=>
string(1) "c"
["D"]=>
string(1) "d"
}
多くのプログラミング言語でも正規表現は実装されているが、実はかなり奥深い。そして、普通の人が聞いたら間違いなく「性器表現」と勘違いする不思議な言葉だ。現在、Oreillyから出版されている『詳細 正規表現 第2版』を読んでいて改めて正規表現について認識する必要があると考え、以下のとおりまとめてみた。これは今後順次改訂していく予定です。
正規表現の種類
正規表現にはPerlやPHP, Java, .NET, Python, Ruby, sedに実装されているNFAとawk, egrep, MySQLで実装されているDFAというものがある。NFAは従来からある正規表現であり、記述方法で動作速度が決まる。つまり、どれだけでも遅い正規表現を書くことが出来る(ひどい場合ではSegumentation Faultとなり、実行できない)と言うことになる。NFAで正規表現を記述するにはそれなりの知識と経験が必要になる。
一方で、DFAは最適化される正規表現であり、効率の悪い正規表現も実行動作前(コンパイル時)に最適化されて実行することになる。
文字クラス
リテラルをグループ化して、いずれか1つをあらわす。
[a-z] 小文字のアルファベットすべて
[^a-z] 小文字のアルファベット以外(「^」を最初におくと文字クラスが否定される)
[0-9] 数字すべて
[a-zA-Z] 大文字小文字を含むアルファベット
[a-zA-Z&[^mM]] 大文字小文字を含むアルファベット。但しMおよびmは除外される。
グループ
複数のパターンを表す。
(a|bc) aまたはbc
(?!a|bc) aでもbcでもない(否定形)
量子指定子
前に付くリテラルならびに文字クラス、グループを修飾する。
* 0文字以上
+ 1文字以上
? 0または1文字
{2,5} 2文字以上5文字以下
{,5} {0,5}の省略
{3,} 3文字以上
NFA拡張(Perl拡張)
NFA拡張にはキャプチャなし括弧(?: ...)、先読み(?= ...)、戻り読み(?<= ...)がサポートされている。
(?:aaa|bbb) aaaまたはbbb。但し(aaa|bbb)と異なり、括弧の中は$1で取得できないようにする(つまりメモリを節約することができる)。
(?<=aaa)bbb 直前にaaaがくるbbbにマッチ(先読み)。
(?<!aaa)bbb 直前にaaaがこないbbbにマッチ(否定先読み)。
aaa(?=bbb) 直後にbbbがくるaaaにマッチ(戻り読み)。
aaa(?!bbb) 直後にbbbがこないaaaにマッチ(否定戻り読み)。
・モード修飾子
多くの言語の場合には、大文字小文字の区別なしや改行を無視するiやxのモードを言語側で用意している。たとえば、Perlでは
$a =~ /a-z/i; #大文字小文字のアルファベットにマッチ
$a =~ /abc
def/x; #abcdefにマッチ(正規表現内の改行とタブを無効化する)
だが、正規表現内でもこれが利用できる。
(?i:[a-z])、(?:x:abc
def)で代用できる。iモード修飾子の場合には、正規表現内で大文字小文字を区別しないケースとするケースを混在させられる便利な修飾子といえる。
・欲張り型と非欲張り型
NFAにはバックトラックと言う機構によってパターンマッチングを行っている。バックトラックを抑止する方法が欲張り型であり、後続のマッチ文字列に配慮することなくマッチングする。逆に量子指定子の働きを最大限抑制する方法が非欲張り型である。いずれもNFAでサポートされている。
.++または(?>.+) 任意の文字列を欲張り型でマッチ(この場合はほとんど全ての文字列にマッチすることになり、後続するマッチ文字列の指定があれば失敗することになる)
.+? 任意の文字列を非欲張り型でマッチ。.+?aは[^a]+と同義となる。また、.*?は[^a]*と同義。バックトラックが起こらない分だけ、それぞれ同義のマッチ文字列の方が早い。
PHPでグラフを描画するライブラリには、JpGraphという有名なライブラリがあるんだけれども、商用利用では有償なのでその他のライブラリについて。
PHPlot
snort+acidにも利用されているらしい。
http://tec-tech.org/phplot5/doc/index-j.php
最終リリースが2004年10月なので、もう枯れた感が否めないが、残念ながら日本語が利用できないみたいだ。
GraPHPite
会社の人に紹介してもらったライブラリ。
PEARに移行済みで、Image_Graphとしてリリース(Ver.0.72 - α版)されている。こちらにサンプルとともにPHPコードがあるので、容易にグラフを作成することが出来る。