パーミッションが違う

2009/09/16 | PHPの基本

ファイルのアップロード処理をする際、アップロードされたファイルを適切な場所に移動させる必要がある場合がある。このとき、一番いいのはmove_uploaded_file関数を使って、ファイルを移動するのがいい。というのは移動元のファイルがアップロードされたファイルなのかどうかをチェックしてくれるからだ。これにより、あらぬセキュリティ問題を考えなくてすむからだ(もちろん他にも問題は山積するのだが)。

ファイルのチェックという意味では、似た機能としてis_uploaded_file()という関数がある。これはHTTP POSTでアップロードしたファイルかどうかをチェックしてくれる関数だ(でもこれは本題ではない)。

ファイルの移動なら、copy関数もあるし、ファイルポインタをopenして(fopen)して、新しいファイル(移動先)に内容を書き込んだりすることでも実現できる。これらの方法はmove_uploaded_file()関数と圧倒的な違いがある(前述のセキュリティの問題を除いて)。それは移動されたファイルのパーミッションだ。CentOS5のデフォルトな環境だと、移動先のファイルは以下のようになる。

move_uploaded_file()で移動した場合・・・600
その他の方法で移動した場合・・・644

なんで違うんだろ。umask()の設定が影響しているんだろうか。前者の場合はapacheの読み書き権限しかないので、FTPでダウンロードとかできないわけで、ちょっと不便だったりする。手間だけど、is_uploaded_file()でチェックしつつ、copy()等で移動するほうが使いやすい(もしくはchmod()か)。やりようはいろいろあるんだけど、一番スマートな方法を極めるためには少し調べる必要がありそうだ。

英数字も数値文字参照

2009/07/19 | PHPの基本

以前、数値文字参照の文字列を作成する方法について記事を書いた。mb_convert_encodingで変換後のエンコーディングにHTML-ENTITIESを指定すれば、数値文字参照に変換することができた。でも、これ、英数字は変換してくれない。

実際の効果のほどはわからないけれどメールアドレスを数値文字参照を使って表現すれば、スパムでもっていかれる確率が少し下がるので、メールアドレスを変換するための関数を書いた。それのメモ。

function str2entities($str){
$value=”;
for($i=0;$i<strlen($str);$i++){
$value.=’&#’.ord(substr($str,$i,1)).';';
}
return $value;
}

引数に変換したいメールアドレスを与えると、数値文字参照で構成されたメールアドレスが返される。マルチバイトでも何でもこいな変換関数を書くのは、mb関数を使うなり適宜工夫すればできそう(今のところ必要ない)。

パスを整理

2009/07/17 | PHPの基本

プログラムを書くときは、相対パスを使うことが多いのだが、../が大量にあったりすると、実際にどのディレクトリが指定されているのかわからなくなることがある。「なんかうまい方法がないかなぁ」と考えたけど、「そんな関数ありそうだよね」と思って調べたらやっぱりあった。

realpath

引数にパスを指定してやると、絶対パスを返してくれる。相対パスを指定しても、おそらくカレントディレクトリを判断して絶対パスを返すだろうし、../を多用してわかりにくくなってしまったパスも整理して絶対パスで返してくれる。便利、便利。

SJISなCSVを読み込む手法

2009/07/13 | PHPの基本

CSVを読み込むためにPHPではfgetcsvという便利な関数が用意されている。だけどPHPで使用できる文字コードの関係で、CSVファイルがシフトJISな場合はデータが破損してしまうことがある。普通なら「文字コードを変換すれば」ということになるが、fgetcsv関数はファイルポインタを引数としてとるため、一旦文字コード変換した内容を一時ファイルに書き出してやらなければならない。しかしこれはスマートでない。また、実はPHPにはそれさえも考慮したstr_getcsv関数があるらしい。こちらは引数として文字列を与えることができる!。しかしこの関数、どうもCVSバージョンだけに存在するらしく、たいていの場合この関数を使用できる環境ではなさそうだ。

実は便利な手法があった。ファイルとして書き出すのではなく「いったんメモリに保存する」というなんともおしゃれな手法だ。やり方としてはこんな感じ。

$text=file_get_contents($filePath);
$text=mb_convert_encoding($text,’UTF-8′,’SJIS’);
$fp=fopen(‘php://temp’,’r+’);
fwrite($fp,$text);
rewind($fp);
while($values=fgetcsv($fp,1024)){
var_dump($values);
}

3行目がおしゃれ。php://tempとすることでメモリに書き出してくれるらしい。しかも容量を考慮して、容量が大きい場合はファイルに書き出してくれたりもする(たぶん一時ファイルとして書き出して処理完了後は消えてくれるんだろうと期待するわけだが)。この行が魅力的なのはr+でオープンしているところ。それは5行目を見れば理解できる。

もう一個ミソが5行目。書き出したファイルを一旦クローズして、再度オープンするなんてことはしない。rewind関数でファイルポインタを最初に戻してやるわけだ。ここでr+オープンした意味が出てくる。書き出しておいて、読み直すわけだ。

すごくかっこいい。多用しそう。でも「php://temp」はPHP5.1という条件付。入出力ストリームは使う機会こそ少ないけれど、要所要所で重要になる使い方だとしみじみ思う次第であった。

PHPで使用中のメモリを知る

2009/07/05 | PHPの基本

PHPでは、設定を変更することで使用するメモリ量の上限値を決めることができる。php.iniのmemory_limitの設定だ。しかしこの値は上限値であって、実際のところどのくらい使っているのかを知らないと、正しく設定することができない。結局変数に格納されているデータを想定(もしくはグローバルに格納された値の容量を調べる)しないといけないのか。

と思ったら、便利な関数がありました。memory_get_usage。この関数を呼び出した時点で、そのプログラムに割り当てられたメモリ量を知ることができるとのこと。素敵な関数だ。

大きな配列やファイルを読み込む必要があるときは重宝しそうだ。


守谷市(まちの情報ポータル) 無料アンケートレンタルjpForm.net