PHPでファイルを扱う処理を作るなら、basename関数を活用してください。とはいえ、basename関数の使い方や、なぜ使うのが理解できない、という方がいるかもしれません。今回は、そのような方に、basename関数の使い方と効果を具体的な例を紹介しながら解説します。
目次
ファイル名の基本
PHPは、Webシステムの構築に向いているプログラム言語ですが、Webサーバー内のファイルを扱うケースもよくあります。しかし、Webサーバー内のファイルを扱うプログラムでは、セキュリティに配慮が必要です。
特に、ファイルのアップロードなど、外部からファイルを取り込む処理では、ユーザーがアップロードしたファイル名をそのまま使えるとは限りません。とはいえ、PHPでファイルを扱う場合の基本が解っていないと、この問題は理解できないでしょう。
そこで、basename関数の使い方やその効果を解説する前に、PHPで扱うファイル名の基本について解説します。
PHPで扱うファイル名の基本
ファイル名といったら「sample.php」といった単純な書き方の他、「/tmp/sample.php」や「../sample.php」といったパス名による書き方もできます。PHPからアクセスできるファイル名の規則は、次のとおりです。
実行したPHPファイルと同じディレクトリにある場合は、ファイル名のみでもアクセスできます。
例 sample.php
絶対パスでパス名を記述したファイル名の場合は、「/」または「\」で全てのパス名とファイル名を記述します。
例 /var/www/export/sample.php (Linuxの場合)
例 D:\www\export\sample.php (Windowsの場合)
実行したPHPファイルから見て、相対パスで記述されたファイルの場合は、相対パスを記述する規則に従います。なお、相対パスとは、カレントディレクトリを「./」とし、1階層上を「../」として、ディレクトリ名を記述する書き方です。
例 ./data/sample.php (カレントディレクトリの下のdataにあるsample.php)
例 ../export/sample.php (1階層上にあるexportディレクトリの下にあるsample.php)
basenameとは
先ほどの絶対パスのファイル名に注目してください。Linuxの場合、「/」(スラッシュ)から「/」(スラッシュ)までがディレクトリの階層です。そして、それにファイル名が続きます。今回扱うbasenameとは、このファイル名のことです。
1 2 3 4 5 6 7 8 |
絶対パスで書かれたパス名 /var/www/export/sample.php パス名に含まれるディレクトリの階層 /var/www/export/ パス名に含まれるファイル名 sample.php |
絶対パスは文字列のため、ここからファイル名のみ抜き出すことは、プログラムで作ることも可能です。しかし、PHPではbasenameという関数を使えば、絶対パスの文字列から、ファイル名のみ抜き出せます。
また、同じように相対パスからで書かれたパス名からも、ファイル名のみ抜き出すことが可能です。
1 2 3 4 5 6 |
相対パスで書かれたパス名 ../export/sample.php パス名に含まれる sample.php |
相対パスの危険性
仮に、相対パスで書かれたファイル名をそのまま使い、Webサーバーのローカルディスクにコピーしたらどうなるでしょうか。例えば、次の悪意のある相対パスで書かれたファイル名が、そのまま書き込まれた場合を考えてください。
格納ディレクトリ
/home/www/public_html/upfile
悪意のあるファイル名
../index.html
この悪意のあるファイルは、「/home/www/public_html/upfile/../index.html」、つまり「/home/www/public_html/index.html」を書き換えてしまい、Webシステムのトップページを書き換えられてしまいます。 フィッシングなどの犯罪に使われる可能性もあるため、bansename関数で「index.html」のみにしなければなりません。
PHPのbasename関数の基本
PHPのbasename関数は絶対パス、または、相対パスで書かれたパス名からファイル名のみを抜き出す関数です。
次から、PHPのbasename関数の基本について紹介します。
basename関数の文法
basename関数は、先ほど紹介したように、パスからファイル名を抜き出すだけのシンプルな関数です。
basename ( パス名 );
なお、実際のファイルシステムで、そのファイルが存在するかのチェックはしません。単純に、文字列としてのパス名から、ファイル名を抜き出すだけです。
1 2 3 4 |
basenameの簡単な例 <?php echo basename("/var/www/export/sample.php") . "\n"; // sample.phpを出力します ?> |
basenameにサフィックスを指定する方法
また、basename関数は、サフィックス文字列を指定し、その文字列を削除したファイル名を出力することも可能です。
basename ( パス. サフィックス );
例えば、先ほどの例の「.php」をサフィックスとして指定し、ファイル名から拡張子を除いた文字列を出力できます。
1 2 3 4 |
basenameでサフィックスを使う例 <?php echo basename("/var/www/export/sample.php", ".php") . "\n"; // sampleを出力します ?> |
basenmaeは日本語も扱える
Windowsでは、よく日本語のフォルダ名やファイル名が使われますが、Linuxでも日本語が使えます。そのため、最近は日本語のディレクトリを含むパス名が珍しくありません。
PHPでは、日本語などのマルチバイトに対応した関数と、そうでない関数とがありますが、basename関数はマルチバイトに対応しています。そのため、日本語を含むパス名も扱えます。
1 2 3 4 |
マルチバイトのパス名でbasenameを使用した例 <?php echo basename(""/var/www/export/試用/sample.php") . "\n"; // sample.phpを出力します ?> |
basename関数の使い方
PHPのプログラムでbasename関数を使い、ファイル名のみ抜き出す処理としてよく使われるのが、Webシステムでファイルをアップロードする処理です。
次から、basename関数を使った例として、Webシステムでファイルをアップロードする処理を例に紹介します。
ファイルアップロードの仕組み
basename関数が使われる例としてよく挙げられるのが、Webシステムにファイルをアップロードする処理です。
HTMLのformタグとinputタグを利用して、ファイルをアップロードした場合、PHPでは、定義済み変数の$_FILESでアップロードしたファイル名を受け取れます。しかし、先ほど解説したように、そのファイル名を、そのままプログラム内で使用してはいけません。
一般的なWebブラウザからファイルをアップする場合、$_FILES[‘upfile’][‘name’]にはファイル名しか格納されていませんが、別の方法で悪意のあるファイルをアップロードされるケースがあります。そのため、<basename関数を使い、ファイル名のみを切り出してプログラム内で使用します。
ファイルアップロードの例
PHPで作られたWebシステムでファイルをアップロードする際、basename関数を利用した例を次に紹介します。
ファイルアップロードの例
1 2 3 4 5 6 7 |
<?php if(isset($_FILES['upfile']) ) { $tmpfile = $_FILES['upfile']['tmp_name']; $filename = "./upload/" . basename($_FILES['upfile']['name']); if(is_uploaded_file($tmpfile)) { move_uploaded_file($tempfile, $filename ) .... |
これは、でアップロードしたファイルのパス名から、ファイル名のみを切り出して、変数$file_nameに格納し、続くプログラムで利用する例です。
Webブラウザで指定したファイル名は$_FILES[‘upfile’][‘name’]に、また、サーバー側にアップロードされたファイル名は$_FILES[‘upfile’][‘tmp_name’]に格納されています。そこで、まずは、サーバー側にアップロードされたファイルを、basename関数でファイル名のみにし、プログラムが管理する”./upload/”ディレクトリの下にコピーします。
まとめ
今回紹介したPHPのbasename関数は、絶対パスや相対パスからファイル名のみを切り出す単純な処理の関数です。そして、今回紹介したように、PHPでファイルを操作する処理で使用します。
スキルのある方なら、basename関数と同じ機能をプログラムで作れるかもしれませんが、basename関数を利用することで、読み易いプログラムを記述できます。
さらに、今回紹介した例のように、Webシステムのセキリティ対策としても有効な関数なので、ぜひ、活用してください。