PHP Logo ディレクトリとファイルの操作

更新日:2018年07月03日

パーミッション

パーミッションとは、UNIX 系システムにおけるファイルやディレクトリ(Windows でのフォルダと同義)ごとに定義された保護モード(アクセス権)のことをを言います。

一般的に Web では複数のユーザーが1台のマシン(UNIXのシステム)を共有するため、自分のファイルを他人に不正に操作されないためにアクセス権(パーミッション)を設定することが出来ます。

「所有者(owner)」、「グループ(group)」、「その他(other)」のユーザー クラスに対してそれぞれ「読み(read)」、「書き(write)」、「実行(execute)」の3種類のパーミッションを指定します。

ファイルアクセス権の割り当てや変更が行えるのは、通常、そのファイルの所有者だけです。

所有権
ユーザー クラス 意味
所有者(owner) ファイル/ディレクトリの所有者。ファイルを作成・アップロードしたユーザー。
グループ(group) ユーザーグループのメンバー。グループはサーバ上で設定できる。グループがなければ、これに対する権限はなしにしてよい。
その他(other) ファイル所有者ではなくグループメンバーでもないその他の全ユーザー。サイト訪問者が閲覧する際のサーバ上の動作には、「その他」の設定が適用される。「その他」の「読み」が指定されていなければ、サイトは閲覧できない。
ファイルアクセス権
パーミッション ファイル ディレクトリ
読み(r) ファイルの内容を開いて読み込むことができます。 ディレクトリ内のファイルを一覧表示できます。
書き(w) ファイルの内容の変更またはファイルの削除を行えます。 ディレクトリに対してファイルまたはリンクを追加できます。また、ディレクトリ内のファイルまたはリンクの削除も行えます。
実行(x) ファイルがプログラム(実行可能ファイル)の場合、そのファイルを実行できます。 ディレクトリ内のファイルを開いたり、実行したりできます。また、ディレクトリを作成し、その下にサブディレクトリを作成できます。
拒否(-) ファイルの読み込み、書き込み、または実行を行うことができません。 ファイルの読み込み、書き込み、または実行を行うことができません。

ファイルアクセス権は以下の記号または数字で表されます。

アクセス権 記号 数字
読むことができる (Readable) r 4
書くことができる (Writable) w 2
実行することができる (eXecutable) x 1
なにもできない - 0

パーミッションの記述方法

パーミッションには「記号表記」と「八進記述」の二通りの記述方法があります。

「記号表記」の場合は、9桁で表記します。3桁ごとに「所有者」、「グループ」、「その他」を示し、それぞれの1桁目は「読み」、2桁目は「書き」、3桁目は「実行」となります。

パーミッションの「記号表記」
r w x r w x r w x
読み 書き 実行 読み 書き 実行 読み 書き 実行
所有者 グループ その他

たとえば自分にはすべての実行権が許可されるが、自分以外のグループや他人には、何も許さないという場合は 「rwx------」という表記になります。

逆にすべての人にすべての実行権を許す場合は、「rwxrwxrwx」という表記になります。但し、これはセキュリティ上問題がある指定なので使用はお勧めしません。

「八進表記」の場合は、「r=4」、「w=2」、「x=1」と数字(属性値)で表します。

記号表記で「rw-r--r--」のものを八進表記に置き換えると、所有者は「r+w=4+2=6」、グループとその他は「r=4」となり、「644」と表記できます。

属性値= 読み+書き+実行
記号 r w x r w x r w x
数字 4 2 1 4 2 1 4 2 1
記号記号表記 r w - r - - r - -
属性値 6 4 4
  4+2+0 4+0+0 4+0+0
  所有者 グループ その他
記号表記と八進表記
アクセス権 記号表記 八進表記
アクセス権なし --- 0
実行 --x 1
書き込み -w- 2
書き込みと実行 -wx 3
読み取り r-- 4
読み取りと実行 r-x 5
読み取りと書き込み rw- 6
全てのアクセス権 rwx 7

よく使われるパーミッションの例

パーミッションの例
ファイル パーミッション
(記号)
パーミッション
(八進)
読むだけの HTML、CSS、画像ファイル等 644
(604)
rw-r--r--
(rw----r--)
データの書き込み、書き換えが必要なファイル 666
(606)
rw-rw-rw-
(rw----rw-)
CGI などサーバー上で実行が必要なファイル 755
(705)
rwxr-xr-x
(rwx---r-x)
.htaccessファイル 644
(604)
rw-r--r--
(rw----r--)
通常のディレクトリ 755
(705)
rwxr-xr-x
(rwx---r-x)

グループを設定していなければ、2桁目の数字は「0」にしておきます。

レンタルサーバーでは、それぞれの仕様で異なる場合があります。

ファイルのパーミッションの変更

ファイルのパーミッションはサーバーの「File Manager」などを利用して変更することができます。

以下は「File Manager」でファイルを表示した例です。

file manager sample

以下はパーミッション変更のダイアログボックスです。

change permission sample

ファイルのパーミッションを取得

ファイルのパーミッションを取得するには、fileperms() 関数を使用します。以下が構文です。

int fileperms( $filename )

パラメータ

  • filename:ファイルへのパス。

戻り値

ファイルのパーミッションを数値モードで返します。 しかし、大半のプラットフォームでは、それだけではなく filename のファイル形式に関する情報も含まれます。

以下は、八進形式でのパーミッションの表示の例です。

fileperms() の結果を sprintf() でフォーマット「%o(8 進数として表現)」を指定し、substr() で最後の4文字を取り出しています。

<?php
echo "カレントディレクトリ :";
echo substr(sprintf('%o', fileperms('.')), -4);
echo "<br>sample.txt  :";
echo substr(sprintf('%o', fileperms('sample.txt')), -4);
?>
カレントディレクトリ :0755
sample.txt :0606

表示される数値モードのパーミッションの1桁目は、特殊なパーミッション(setuid、setgid、スティッキービット)を示す数字が入っています。

chmod() / umask()

PHP でファイルのモードを変更 chmod()

ファイルのモードを変更するには、chmod() 関数を使用します。以下が構文です。

bool chmod( $filename , $mode )

指定されたファイルのモードを mode で指定したものに変更しようと試みます。

パラメータ

  • filename:ファイルへのパス。
  • mode:mode は自動的には 8 進数と見なされないので注意してください。 意図した操作を行うには、mode の前にゼロ(0)を付ける必要があります。 "g+w" のような文字列は正常に動作しません。

戻り値

成功した場合に TRUE を、失敗した場合に FALSE を返します。

注意:
通常、ファイルの所有者のみがそのモードを 変更可能です。また、この関数では、 リモートファイル を 使用することはできません。これは、処理されるファイルがサーバーの ファイルシステムによりアクセスできる必要があるためです。

以下はサンプルです。

<?php
$result = chmod("sample.txt", 0606);
var_dump($result);
echo "<br>";
echo substr(sprintf('%o', fileperms('sample.txt')), -4) ."<br>";
?>
bool(true)
0606

ユーザーマスク umask()

ファイルまたはディレクトリを作成したときに設定されるデフォルトのファイルアクセス権は、ユーザーマスク(umask)によって制御されます。

別の言い方をすると、新規作成されるファイルやディレクトリのパーミッションを制御するのが umask です。

umask では、許可しないビットを指定します。

mkdir() 関数でディレクトリ(フォルダ)を作成する際など、モードを 0777 に指定しても、0755 になってしまうことがあります。これは、umaskが「0022」と設定されているためです。(0777 - 0022 = 0755)

同様にファイルのパーミッションも、モードを 0666 に指定しても、umaskが「0022」に設定されていると 0644 になります。

default 0666 rw-.rw-.rw-
umask   0022 ---.-w-.-w-
Final   0644 rw-.r--.r--

通常、システムのデフォルトのファイル・パーミッションは、0666 で、ディレクトリのパーミッションは 0777 になっています。また、 通常の PHP の umask は 0022 になっています。

現在の umask の設定がどうなっているかは、umask() 関数をパラメータなしで実行するとわかります。

<?php
echo decoct(umask());   //22 と表示される
?>

※ umask() の戻り値は10進数なので、8進数に変換するため decoct() を使っています。上記の場合、decoct() を使用しないと 18(10進数)が返ります。

以下が umask() の構文です。

int umask ([ $mask ] )

umask() は現在の umask を変更します。
注意:変更後元に戻すのを忘れると問題が発生する可能性があります。

パラメータ

  • mask(int):新しい umask の値。(例)umask(0022) 
    注意 umask(22) としてしまうと 22(10進数)が 0026(8進数)に変換され、umask(0026) を指定したことになります。

戻り値

umask() を引数無しで実行すると、単に現在の umask 値を返します。 但し、戻り値は10進数なので、必要に応じて decoct() などを使って8進数に変換します。

注意:
マルチスレッドな Web サーバーでこの関数を使用することは避けてください。 ファイルを生成後、chmod() を使用してファイル権限を 変更するのがより良い方法です 。

全て同じ umask が使用されるので、 umask() の使用は、スクリプトを同時に実行する場合や Web サーバー自身の予期しない動作を引き起こす原因になる可能性があります。

ディレクトリの操作

ディレクトリ情報の取得

以下は、サーバー上の特定のディレクトリ(フォルダ)の中のファイルの情報を一覧表示する例です。

<table>
<tr>
<th>ファイル名</th><th>ファイルサイズ</th><th>最終アクセス日</th><th>最終更新日</th>
</tr>
<?php
clearstatcache();
$handle = opendir('./');
if($handle) {
  while(false !== ($file = readdir($handle))) {
    if($file != '..' && $file != '.') {
      echo "<tr>";
      echo "<td>".$file ."</td>";
      echo "<td>".filesize($file). " byte </td>";
      echo "<td>".date("y/m/d H:i:s", fileatime($file))."</td>";
      echo "<td>".date("y/m/d H:i:s", filemtime($file))."</td>";
      echo "<tr>\n";
    }
  }
}

closedir($handle);
?>
</table>
ファイル名ファイルサイズ最終アクセス日最終更新日
php_basic_02.php167565 byte 18/07/23 02:04:0018/07/20 23:29:32
_notes4096 byte 18/07/22 06:50:2218/04/23 20:40:48
newfile.txt884 byte 18/04/24 16:57:5315/11/25 01:06:52
access_couner.txt4 byte 18/07/23 07:05:3018/07/23 07:05:30
php_basic_08.php66927 byte 18/07/22 22:31:4018/07/02 14:15:18
php_basic_11.php95435 byte 18/07/23 02:04:0218/07/02 14:15:29
php_basic_09.php205405 byte 18/07/23 02:04:0118/07/02 14:15:22
db_info.php132 byte 18/04/24 06:22:0816/07/07 02:13:34
sample_text.txt91 byte 18/07/23 06:08:2915/11/22 22:31:08
sample3.txt39 byte 18/04/24 16:57:5415/11/21 19:44:40
php_basic_03.php104689 byte 18/07/23 03:35:1118/07/02 15:50:09
last_modified.php96 byte 18/07/23 01:01:1518/07/03 15:51:48
index.html7287 byte 18/07/23 02:03:5918/04/29 19:45:25
php_basic_01.php214722 byte 18/07/22 11:49:5618/07/09 00:02:13
access_log.txt707 byte 18/04/24 16:57:5315/11/22 19:13:20
sample4.txt25 byte 18/07/23 07:05:3018/07/23 07:05:30
php_basic_06.php178867 byte 18/07/23 02:04:0118/07/22 00:50:25
sample.txt51714 byte 18/07/22 16:49:1518/07/23 07:05:30
php_basic_04.php149102 byte 18/07/23 06:08:2918/07/03 21:11:28
php_basic_10.php148005 byte 18/07/23 02:04:0218/07/02 14:15:26
introduction.html28572 byte 18/07/22 14:58:2218/06/22 21:44:11
fruits.txt125 byte 18/04/24 16:57:5315/11/23 00:23:58
sample2.txt0 byte 18/04/23 20:39:3218/07/23 07:05:30
php_basic_07.php199847 byte 18/07/23 01:43:2418/07/21 21:03:10
php_basic_05.php95487 byte 18/07/22 23:37:1218/07/02 14:15:06
opendir() を使った操作

以下は opendir() を使用して情報を取得するおおまかな流れです。

  • clearstatcache() でファイル情報のキャッシュをクリア。
  • opendir() で特定のディレクトリにアクセス。
  • readdir() でディレクトリ配下のファイルを読み込み、ファイルの情報を取得。
  • closedir() で処理の終わったディレクトリハンドルをクローズ。

clearstatcache()

PHP はパフォーマンス向上のために ファイルシステム関数の戻り値をキャッシュします。

clearstatcache() 関数を使用することで ファイルの情報に関してPHPが持っているキャッシュをクリアすることができます。

最新の最終更新日などの情報を取得するには、clearstatcache() 関数でキャッシュをクリアする必要があります。以下が構文です。

void clearstatcache ([ $clear_realpath_cache [, $filename ]] )

パラメータ

  • clear_realpath_cache(bool):realpath キャッシュをクリアするか否か。デフォルトは FALSE。
  • filename(string): realpath キャッシュと stat キャッシュを特定のファイル名だけに対してクリアする。 clear_realpath_cache が TRUE の場合にのみ使用

戻り値

値を返しません。

opendir()

opendir() 関数は、特定のディレクトリにアクセスするのに使用します。この関数は、指定されたディレクトリの取得に成功すると、ディレクトリハンドルを返します。

ディレクトリハンドルは、指定されたディレクトリを操作(ハンドル)するための情報のようなもので、後続のディレクトリを操作する関数で使用します。

以下が構文です。

resource opendir($path)

ディレクトリハンドルをオープンします。このハンドルは、この後 closedir(), readdir(), rewinddir() 関数コールで使用されます。

パラメータ

  • path(string):オープンするディレクトリのパス。

戻り値

成功した場合にはディレクトリハンドルのリソースを 、失敗した場合には FALSE を返します。(参考:リソース

ディレクトリが オープンできない場合、opendir() は FALSE を返し、 E_WARNING エラーが発行されます。 opendir() のこのエラー出力は、 関数名の前に '@' (エラー制御演算子)を付けることにより抑制できます。

readdir()

readdir() 関数は、ディレクトリ配下のファイル(サブディレクトリ)を読み込むための関数です。以下が構文です。

string readdir ([ $dir_handle ] )

readdir() 関数は、ディレクトリから次のエントリの名前を返します。 エントリ名はファイルシステム上に格納されている順番で返されます。

パラメータ

  • dir_handle(resource):opendir() が事前にオープンしたディレクトリハンドルリソース。 ディレクトリハンドルを指定しなかった場合は、 opendir() が最後にオープンしたものを使用します。

戻り値

成功した場合にエントリ名、失敗した場合に FALSE を返します。

注意:この関数は論理値 FALSE を返す可能性がありますが、FALSE として評価される値を返す可能性(ファイル名やディレクトリ名が 0 などの場合)もあります。この関数の返り値を調べるには ===演算子(!==演算子)を使用します。

以下の例は、readdir() の戻り値を調べる場合の正しい方法と誤った方法です。

<?php
if ($handle = opendir('/path/to/files')) {

  /* ディレクトリをループする際の正しい方法 */
  while (false !== ($entry = readdir($handle))) {
    echo "$entry\n";
  }

  /* ディレクトリをループする際の「間違った」方法 */
  while ($entry = readdir($handle)) {
    echo "$entry\n";
  }

  closedir($handle);
}
?>

ディレクトリをループする方法

while (false !== ($entry = readdir($handle))) {
  echo "$entry\n";
}

readdir() は、読み込みに成功した場合は次のファイル名を返し、次のファイルがない場合は FALSE を返します。その性質を利用して readdir() が FALSE を返すまで while ループを繰り返し、ディレクトリの配下の全てのファイルを取得することができます。

また、readdir() は、特別なファイルとして「.」(カレントディレクトリ)と「..」(上位のディレクトリ)を返します。

以下は、「.」 および 「..」 以外のカレントディレクトリの全てのエントリを表示する例です。

<?php
if ($handle = opendir('.')) {
  while (false !== ($entry = readdir($handle))) {
    if ($entry != "." && $entry != "..") {
      echo "$entry <br>";
    }
  }
  closedir($handle);
}
?>
php_basic_02.php
_notes
newfile.txt
access_couner.txt
php_basic_08.php
php_basic_11.php
php_basic_09.php
db_info.php
sample_text.txt
sample3.txt
php_basic_03.php
last_modified.php
index.html
php_basic_01.php
access_log.txt
sample4.txt
php_basic_06.php
sample.txt
php_basic_04.php
php_basic_10.php
introduction.html
fruits.txt
sample2.txt
php_basic_07.php
php_basic_05.php

各ファイルに関する情報を取得するには、以下のファイルシステム関数を使用しています。

  • filesize() : ファイルサイズ(バイト単位)を取得
  • fileatime() : ファイルの最終アクセス日時(タイムスタンプ)を取得
  • filemtime() : ファイルの最終更新日時(タイムスタンプ)を取得

fileatime() と filemtime() はタイムスタンプを返すので、date() 関数を使用して適当なフォーマットに整形します。

closedir()

処理の終わったディレクトリハンドルは、closedir() 関数でクローズします。以下が構文です。

void closedir ([ $dir_handle ] )

dir_handle で指定したディレクトリのストリームをクローズします。このストリームは、 opendir()により事前にオープンされていなければ なりません。

パラメータ

dir_handle(resource):opendir() が事前にオープンした ディレクトリハンドルリソース。 ディレクトリハンドルを指定しなかった場合は、 opendir() が最後にオープンしたものを使用します。

戻り値

値を返しません。

rewinddir()

ディレクトリハンドルをディレクトリの先頭にリセットするには、rewinddir() 関数を使います。以下が構文です。

void rewinddir ([ $dir_handle ] )

dir_handle で指定されたディレクトリの ストリームをディレクトリの先頭にリセットします。

パラメータ

dir_handle(resource):opendir() が事前にオープンした ディレクトリハンドルリソース。 ディレクトリハンドルを指定しなかった場合は、 opendir() が最後にオープンしたものを使用します。

戻り値

値を返しません。

dir() を使った操作

dir() 関数を使用して生成したディレクトリオブジェクトの read() メソッドを使い、ファイル名(ディレクトリ名)を1つずつ取り出して表示します。

以下は、dir() 関数の構文です。

Directory dir( $directory )

dir() はディレクトリクラスのインスタンスを返します。

パラメータ

  • directory(string):オープンするディレクトリ名。

戻り値

Directory のインスタンスを返します。 パラメータが間違っている場合は NULL、それ以外のエラーの場合は FALSE を返します。

以下はディレクトリオブジェクトの read() メソッドを使ってファイル名を取得して配列に格納し、sort() で昇順に並び替えて出力する例です。

  • clearstatcache() でファイル情報のキャッシュをクリアします。
  • dir() 関数の戻り値の $dir(ディレクトリオブジェクトのインスタンス)の read() メソッドを呼び出すと、ディレクトリの中身を1つ取得できます。
  • 取得したファイル名またはディレクトリ名を $filename に代入します。
  • ディレクトリの中身がなくなると $filename には FALSE が入ります。
  • ディレクトリの中身がなくなるまで while 文でループします。
  • 比較演算子には「!==」(厳密な一致)を使用します。「!=」を使用すると、 FALSE と評価されるファイル名があると、そこでループが終了してしまいます。
  • また、ファイルのみを表示するため、is_file() でファイルかどうかを確認して、配列に格納しています。
  • read() メソッドでの読み込みが完了したら、$dir の close() メソッドを呼び出してディレクトリを閉じます。
<?php
clearstatcache();
$dir_name = './';
if($dir = dir($dir_name)) {
  while(FALSE !== ($filename = $dir -> read())) {
    if(is_file($filename)) {
      $file_array[] = $filename;
    }
  }
}
$dir -> close();
sort($file_array, SORT_STRING);
echo '<pre>';
print_r($file_array);
echo '</pre>';
?>
Array
(
    [0] => access_couner.txt
    [1] => access_log.txt
    [2] => db_info.php
    [3] => fruits.txt
    [4] => index.html
    [5] => introduction.html
    [6] => last_modified.php
    [7] => newfile.txt
    [8] => php_basic_01.php
    [9] => php_basic_02.php
    [10] => php_basic_03.php
    [11] => php_basic_04.php
    [12] => php_basic_05.php
    [13] => php_basic_06.php
    [14] => php_basic_07.php
    [15] => php_basic_08.php
    [16] => php_basic_09.php
    [17] => php_basic_10.php
    [18] => php_basic_11.php
    [19] => sample.txt
    [20] => sample2.txt
    [21] => sample3.txt
    [22] => sample4.txt
    [23] => sample_text.txt
)

Directory クラス

Directory クラスには以下のプロパティとメソッドがあります。

 Directory {
    /* プロパティ */
    public string $path ;
    public resource $handle ;
    /* メソッド */
    public void close ([ resource $dir_handle ] )
    public string read ([ resource $dir_handle ] )
    public void rewind ([ resource $dir_handle ] )
}
scandir() を使った操作

scandir() 関数は指定されたパスのファイルとディレクトリのリストを取得します。以下が構文です。

array scandir( $directory [, $sorting_order ] )

指定された directory 内のファイルおよびディレクトリを 配列で返します。(PHP5 以上)

パラメータ

  • directory(string):調べるディレクトリ。
  • sorting_order(int):デフォルト(0)では、ソート順はアルファベット昇順です。
    オプションの sorting_order に SCANDIR_SORT_DESCENDING を設定(1)した場合(1)、 ソート順はアルファベット降順になります。
    SCANDIR_SORT_NONE を設定(2)すると、 結果をソートせずに返します。

戻り値

成功した場合にファイル名(ディレクトリ名)の配列、失敗した場合に FALSE を返します。 directory がディレクトリではない場合は、 FALSE を返し、E_WARNING レベルのエラーを 発行します。

以下は、scandir() 関数を使って指定したディレクトリ内の昇順及び降順のファイルとディレクトリのリストを出力する例です。この例では @(エラー制御演算子)を使ってエラーを出力しないようにしています。

<?php
$dir_name = './';
if(@$file_array_asc = scandir($dir_name)) {
  echo '<pre class="nb">';
  print_r($file_array_asc);
  echo '</pre>';
}

if(@$file_array_desc = scandir($dir_name, SCANDIR_SORT_DESCENDING)) {
  echo '<pre>';
  print_r($file_array_desc);
  echo '</pre>';
}
?>
Array
(
    [0] => .
    [1] => ..
    [2] => _notes
    [3] => access_couner.txt
    [4] => access_log.txt
    [5] => db_info.php
    [6] => fruits.txt
    [7] => index.html
    [8] => introduction.html
    [9] => last_modified.php
    [10] => newfile.txt
    [11] => php_basic_01.php
    [12] => php_basic_02.php
    [13] => php_basic_03.php
    [14] => php_basic_04.php
    [15] => php_basic_05.php
    [16] => php_basic_06.php
    [17] => php_basic_07.php
    [18] => php_basic_08.php
    [19] => php_basic_09.php
    [20] => php_basic_10.php
    [21] => php_basic_11.php
    [22] => sample.txt
    [23] => sample2.txt
    [24] => sample3.txt
    [25] => sample4.txt
    [26] => sample_text.txt
)
Array
(
    [0] => sample_text.txt
    [1] => sample4.txt
    [2] => sample3.txt
    [3] => sample2.txt
    [4] => sample.txt
    [5] => php_basic_11.php
    [6] => php_basic_10.php
    [7] => php_basic_09.php
    [8] => php_basic_08.php
    [9] => php_basic_07.php
    [10] => php_basic_06.php
    [11] => php_basic_05.php
    [12] => php_basic_04.php
    [13] => php_basic_03.php
    [14] => php_basic_02.php
    [15] => php_basic_01.php
    [16] => newfile.txt
    [17] => last_modified.php
    [18] => introduction.html
    [19] => index.html
    [20] => fruits.txt
    [21] => db_info.php
    [22] => access_log.txt
    [23] => access_couner.txt
    [24] => _notes
    [25] => ..
    [26] => .
)

以下は、scandir() 関数の戻り値の配列を foreach() を使って、ファイルの場合のみ表示する例です。

<?php
$dir_name = './';
if($file_array_asc = scandir($dir_name)) {
  echo '<pre>';
  foreach($file_array_asc as $filename) {
    if(is_file($filename)) { //ファイルかどうか
      echo $filename . "\n";
    }
  }
  echo '</pre>';
}
?>
access_couner.txt
access_log.txt
db_info.php
fruits.txt
index.html
introduction.html
last_modified.php
newfile.txt
php_basic_01.php
php_basic_02.php
php_basic_03.php
php_basic_04.php
php_basic_05.php
php_basic_06.php
php_basic_07.php
php_basic_08.php
php_basic_09.php
php_basic_10.php
php_basic_11.php
sample.txt
sample2.txt
sample3.txt
sample4.txt
sample_text.txt

ディレクトリの作成・削除

ディレクトリの作成 mkdir()

ディレクトリ(フォルダ)を作成するには、mkdir() 関数を使います。以下が構文です。

bool mkdir( $pathname [, $mode [, $recursive ]] )

パラメータ

  • pathname(string):ディレクトリのパス。
  • mode(int):モードは 0777 がデフォルトです。 これは最も緩やかなアクセス制限を意味します。 モードを八進数で指定する場合は先頭にゼロをつける必要があります。
    注意: Windows では mode は無視されます。
  • recursive(bool):pathname で、入れ子構造のディレクトリの作成を許可します。(デフォルトは FALSE)

★ モードは、現在設定されている umask の影響も受けます。

戻り値

成功した場合に TRUE を、失敗した場合に FALSE を返します。

また、ディレクトリが既に存在する場合は E_WARNING レベルのエラーが発生し、ディレクトリの作成権限がない場合は E_WARNING レベルのエラーが発生します。

以下は、同じ名前のディレクトリが存在しなければ、ディレクトリを作成する例です。

<?php
//作成するディレクトリのパス
$directory_path = "../test";   
 
if(file_exists($directory_path)){
  echo "指定したディレクトリは既に存在します";
}else{
  if(mkdir($directory_path)){
    echo $directory_path. "を作成しました。";
  }else{
    echo "ディレクトリの作成に失敗しました。";
  }
}
?>

5行目の if 文で、file_exists() を使って指定したディレクトリがすでに存在するかを確認しています。

ディレクトリ作成時にパーミッションを指定する

mkdir() 関数の第2パラメータにパーミッション「0777」を指定しても、ほとんどの場合は指定したパーミッションになりません。

これは、現在設定されている umask の影響を受けるためです。

ディレクトリのパーミッションを「0777」にして作成したい場合や、ファイルのパーミッションを「0666」にして作成したい場合等には、ディレクトリを作成後、chmod() を使用します。

<?php
$directory_path = "../test2";   
mkdir($directory_path, 0777);
chmod($directory_path, 0777);
echo substr(sprintf('%o', fileperms($directory_path)), -4);
?>

5行目は、fileperms() を使ってファイルのパーミッションを取得して表示しています。

umask() 関数を使う方法

umask() 関数を使って以下のようにすることも可能です。但し umask の値を元に戻す必要があります。※前述の chmod() を使用した方法が確実(安全)だと思います。

<?php
$directory_path = "../test";
$mask = umask();  //事前のマスク値を取得して変数に格納
umask(0);  //マスクを無効にする→「0000」に変更
mkdir($directory_path, 0777); 
umask($mask);  //マスク値を元に戻す(必ず実行)
echo substr(sprintf('%o', fileperms($directory_path)), -4);
?>

入れ子構造のディレクトリの作成

第3パラメータ(recursive)を「TRUE」に指定すると、入れ子構造のディレクトリを作成することができます。

以下のように、recursive パラメータを「TRUE」に指定すると、一度に「depth1」「depth2」「depth3」という3つのフォルダを作成することができます。

  • depth1 が存在する場合は depth2, depth3 という2つのフォルダが作成されます。
  • depth1, depth2 が存在する場合は depth3 という1つのフォルダが作成されます。
  • depth1, depth2, depth3 が全て存在する場合はエラーになります。
<?php
$structure = './depth1/depth2/depth3/';

if(file_exists($structure)){
  echo "指定したディレクトリは既に存在します";
}else{
  if(!mkdir($structure, 0777, true)){
    echo "ディレクトリの作成に失敗しました。";
  }
}
?>

入れ子構造ディレクトリの作成でのパーミッションの指定

入れ子構造ディレクトリの作成の際に全てのフォルダにパーミッションを指定する場合は、作成される全てのフォルダにパーミッションを指定する必要があります。

以下のように、記述した場合 chmod() によりパーミッションが設定されるのは「depth3」のみになります。

<?php
$structure = './depth1/depth2/depth3/';
mkdir($structure, 0777, true);
chmod($structure, 0777);
?>

全てのフォルダにパーミッションを指定する場合は、作成される全てのフォルダにパーミッションを指定します。

<?php
$structure = './depth1/depth2/depth3/';
mkdir($structure, 0777, true);
chmod($structure, 0777);   //または chmod('./depth1/depth2/depth3/', 0777);
chmod('./depth1/', 0777);
chmod('./depth1/depth2/', 0777);
?>pre>

ディレクトリの削除 rmdir()

ディレクトリを削除するには、rmdir() 関数を使用します。以下が構文です。

bool rmdir( $dirname )
  • dirnameで指定されたディレクトリを削除しようと試みます。
  • ディレクトリは空でなくてはならず、また 適切なパーミッションが設定されていなければなりません。
  • 失敗した場合は E_WARNING レベルのエラーが発生します。

パラメータ

  • dirname(string):ディレクトリへのパス。

戻り値

成功した場合に TRUE を、失敗した場合に FALSE を返します。

以下は、「examples」というディレクトリが存在する場合にディレクトリを削除する例です。

<?php 
if (is_dir('examples')) {
   rmdir('examples');
}
?>

is_dir() 関数は、指定したファイルがディレクトリかどうかを調べます。ファイルが存在して、かつそれがディレクトリであれば TRUE、それ以外の場合は FALSE を返します。

ファイルの操作

以下は、ファイルシステム関数を使ってのファイルの操作についてです。

ファイルを扱う処理の流れ

ファイルシステム関数を使って、「開く」、「ロックする」、「読み書きする」、(「出力をフラッシュ」)、「ロック解除」、「閉じる」という流れで処理します。

  1. ファイルを開く(モードを指定:読む/書く)fopen()
  2. ファイルをロックする flock()
  3. ファイルを読む/書く fgets(), fread() /fwrite()
  4. 出力をフラッシュ fflush() *書き込みの際に、ファイルをロックした場合
  5. ロックを解除 flock($fp, LOCK_UN)
  6. ファイルを閉じる fclose()

PHP 5.3.2 からファイルのリソースハンドルを閉じたときにロックを自動的に解放する機能が削除されました。 ロックの解放は、常に手動で行わなければなりません。

また、アンロック(ロック解除)の前に、明示的に fflush() を呼び出してバッファの内容をはき出すようにします。

参考:「PHP5.3.2以降ではfcloseで自動的にアンロックされない

以下はテキストファイルへの書き込みの例です。

<?php
$samplefile = 'sample.txt';
$fp = fopen($samplefile, 'wb');
if(!$fp) {
  exit("ファイルが存在しないか異常があります。");
  //ファイルが開けない場合は、終了
}
if(!flock($fp, LOCK_EX)) {
  exit("ファイルをロックできませんでした。");
  //ファイルをロックできない場合は、終了
}
fwrite($fp, "Hello Universe!");  //ファイルに書き込み
fflush($fp);  // 出力をフラッシュ
flock($fp, LOCK_UN);  // ロックを解放
fclose($fp);  //ファイルをクローズ
?>   

exit() は、現在のプログラムを終了する関数です。それ以降のコードは実行されません。

ファイルを開く fopen()

fopen() 関数の第1パラメータにファイル名、第2パラメータに「読む/書く」のモードを指定してファイルを開きます。

以下が構文です。

resource fopen( $filename , $mode [, $use_include_path ] )

パラメータ

  • filename(string):ファイル名。ローカルパスの他に、URL 形式のパス(http://~など)を指定して外部のファイルを開くことも可能です。
  • mode(string):開いたファイルに対して実行できる操作を指定します。読み込み、書き込みなど用途に応じて指定します。追加書き込みをする場合は、「a」、「a+」を使用します。その他の書き込みのモードでは、ファイルの内容が毎回クリアされてしまいます。表「fopen()で使用可能な mode のリスト」を参照。
  • use_include_path(bool): TRUE (または 1)を設定することにより、include_path パラメータ(php.ini)で指定したディレクトリのファイルの検索も行うこともできます。 デフォルトは false。

注意:
外部のファイル(リモートファイル)の操作を許可することは、セキュリティホールの一因となる可能性があります。リモートファイルの操作が不要な場合は、php.ini の「allow_url_fopen」パラメータを「off」に設定するようにします。

また、fopen() で操作できる範囲をより厳しく制限したい場合は、php.ini の「open_basedir」パラメータで任意のパスを指定しておくと、 fopen() は指定のパスの配下にあるファイル以外を開くことができなくなります。

ファイルは PHP からアクセスできるものでなければなりません。 ファイルのパーミッションがアクセスを許可されているかどうか確認する必要があります。

戻り値

ファイルのオープンに成功した場合は、ファイルハンドルを返し、失敗した場合は戻り値として FALSE を返し、 E_WARNING レベルのエラーを発行します。 @(エラー制御演算子)を使ってこの warning を抑制することもできます。

mode/ファイルポインタ

ファイルを操作する用途(読み込み、書き込み、両方)を考慮してモードを指定します。

ファイルポインタとはファイルの中で読み込みや書き込みを行う位置を表します。

ファイルポインタが先頭で読み込みをする場合、ファイルの先頭から読み込みを行います。先頭から書き込みを行うということは既にファイルに何か書いてあった場合、既存の内容を上書きします。また、ファイルポインタが最後ということは既存の内容の最後に追記します。

fopen() で使用可能な mode のリスト
mode 読み書き ファイルなし ファイルあり ポインタ
'r' 読み込みのみ エラー 開く 先頭
'r+' 読み込み/書き込み エラー 開く 先頭
'w' 書き込みのみ 新規作成 ファイルサイズを
ゼロにして開く
先頭
'w+' 読み込み/書き込み 新規作成 ファイルサイズを
ゼロにして開く
先頭
'a' 書き込みのみ 新規作成 開く 終端
'a+' 読み込み/書き込み 新規作成 開く 終端
'x' 書き込みのみ 新規作成 エラー 先頭
'x+' 読み込み/書き込み 新規作成 エラー 先頭
'c' 書き込みのみ 新規作成 開く 先頭
'c+' 読み込み/書き込み 新規作成 開く 先頭

注意:
互換性維持のために、 fopen() でファイルをオープンする際は 常に 'b' フラグを指定することが強く推奨されています。モードが「r+」の場合、「r+b」と記述します。

ファイルをロックする flock()

ファイルを利用する際は、同時にアクセスされる可能性を考慮する必要があります。

  • 読み込みの際に他から書き込まれないようにする。
  • 書き込みの際に他から読み書きされないようにする。

そのため、ファイルをロックしてアクセスを制御します。

fopen() でファイルを開いた直後に、flock() を使って共有ロック、排他的ロックを行います。

flock() 関数の構文は以下です。

bool flock( $handle , $operation )

パラメータ

  • handle(resource):fopen() を使用した際に、返されるファイルハンドル。
  • operation(int):以下のいずれかとなります。
flock() 関数のロック
意味
LOCK_SH 共有ロック。読み込みの場合に使用するロック。(書き込みのみをブロックします)
LOCK_EX 排他的ロック。書き込みの場合に使用するロック。(読み込み・書き込み両方をブロックします)
LOCK_UN ロックを解除します。
LOCK_NB ロックされている場合、FALSE を返します。(このオプションは単独では使用しません)

LOCK_SH, LOCK_EX でのロックは、ブロックモードといって、ロックを確保できるまでいつまでも待ち続ける状態になります。つまりロックできるまで待ってからロックします。

待機させるのではなくすぐにロック失敗とさせる場合に「LOCK_NB」を使います。「LOCK_NB」を使うとロックが解除されるのを待たずに、FALSE が返されます。(ロックされている場合にロックが解除されるのを待たずにすぐに次の処理をしたい場合など)

「LOCK_NB」は単独で指定するのではなく「LOCK_SH | LOCK_NB」や「LOCK_EX | LOCK_NB」のように他の値と同時に指定します。

戻り値

成功した場合に TRUE を、失敗した場合に FALSE を返します。

ロックの解除

ロックを解除するには、第2パラメータに「LOCK_UN」を指定します。

flock($fp, LOCK_UN);

ファイルの書き込み fwrite()

ファイルの書き込みには、fwrite() 関数または fputs() 関数などを使用します。

(注)fwrite() と fputs() は同じものです(エイリアス)。

以下は、fwrite() の構文です。

int fwrite( $handle , $string [, $length ] )

この関数ではバイナリモード(改行の変換が行われない)で書き込みが行われます。

パラメータ string の内容をファイルに書き込みます。書き込む位置は、fopen() で指定したモードにより異なります。

length でバイト数が指定されている場合は、バイト数分だけ書き込みます。指定したバイト数よりも文字列が小さい場合には文字列を書き込んだ時点で終了します。

パラメータ

  • handle(resource): fopen() を使用した際に、返されるファイルハンドル
  • string(string): 書き込む文字列
  • length(int): 一度に書き込む最大バイト数

戻り値

書き込んだバイト数、またはエラー時に FALSE を返します。

書き込まれる位置

  • ファイルの書き込みの場合、fopen() の「w」「w+」「r+」「x」「x+」「c」「c+」のモードでは、ファイルポインタがファイルの先頭になるので、上書きされます。

  • 「w」「w+」のモードの場合、ファイルの中身を空にして、先頭から書き込みを行うので、注意が必要です。

  • 「a」「a+」のモードでは、ファイルポインタが終端にあるので追記になります。

また fwrite() はバイナリモードで書き込むので、Windows 環境で使う場合には fopen() のモードに「b」を追加する必要があります。

例:「ab」「wb」「r+b」等

バイナリモードとテキストモード

テキストファイルの表現方法は、オペレーティングシステムによって異なります。例えば、UNIX 環境における行末は、改行文字 '\n' で表します。また、Windows のシステムでは、行末は、キャリッジリターンと改行 '\r\n' で表します。

テキストモードではこの違いを吸収するため、Windows では '\r\n' を '\n' に変換して読み込みます。また、書き込みのときは逆のことをします。つまり、テキストモードを使うと、「適切な改行コード」が自動的に変換ます。

バイナリモードでは、このような変換は行われません。

改行文字

改行文字は使用しているオペレーティングシステムによって異なるので、 fwrite() で改行文字を使用する際は注意が必要です。

  • Unix 環境:\n
  • Windows 環境:\r\n
  • Mac 環境:\r

以下は、ファイル書き込みの例です。

<?php
$data = "テスト用の文字列です。\n";

$fp = fopen('sample.txt', 'ab');

if ($fp){
  if (flock($fp, LOCK_EX)){
    if (fwrite($fp,  $data) === FALSE){
      print('ファイル書き込みに失敗しました');
    }else{
      print('以下の内容をファイルに書き込みました。<br>' . $data);
    }
    fflush($fp);
    flock($fp, LOCK_UN);
  }else{
    print('ファイルロックに失敗しました');
  }
}
fclose($fp);
?>    
以下の内容をファイルに書き込みました。
テスト用の文字列です。

一度に書き込む最大バイト数の指定

第3パラメータは省略可能ですが、大きいサイズを書き込もうとする場合などは、指定した方が無難なようです。

書き込みたい文字列の長さがわかっていて「一定長以上のデータは書き込みたくない」などの場合はいいのですが、全部書き込みたい場合など、指定する数値がわからない場合は、strlen() 関数を使って文字列の長さを取得して指定します。

<?php
//以下はファイルが開けない場合等は考慮していません
$filename = 'sample3.txt';
$string = "この文字が書き込まれます。"; 
$fp = fopen($filename, 'wb');
flock($fp, LOCK_EX);
//第3パラメータを strlen() を使って指定
fwrite( $fp, $string, strlen($string) ); 
fflush($fp);
flock($fp, LOCK_UN);
fclose($fp);
?>

ファイルを閉じる fclose()

ファイルを閉じるには fclose() 関数を使用します。

以下が構文です。

bool fclose( $handle )

handle が指しているファイルをクローズします。

パラメータ

  • handle(resource):ファイルポインタは有効なものでなければならず、また fopen() または fsockopen() で正常にオープンされたファイルを指している必要があります。

戻り値

成功した場合に TRUE を、失敗した場合に FALSE を返します。

以下は、ファイルを開いて、そのまま閉じる例です。通常はファイルを開いた後に何らかの処理を行い、ファイルを閉じることになります。

<?php
$fp = fopen('sample2.txt', 'w+b');
//何らかの操作を実行
$flag = fclose($fp);

if ($flag){
    print('ファイルをクローズしました');
}else{
    print('ファイルのクローズに失敗しました');
}
?>  
ファイルをクローズしました

ファイルの読み込み fgets()

fgets() はファイルハンドルで指定したファイルから内容を1行読み込む関数です。

以下は、fgets() を使用してファイルを読み込んで表示する例です。

<?php
$filename = "sample.txt";
if(file_exists($filename)){
  $fp = fopen($filename, 'r');
  if(!$fp) {
    exit("ファイルをオープンできませんでした。");
  } else {
    while($line = fgets($fp)) {
      echo $line."<br>\n";
    }
    fclose($fp);
  }
}
?>   

3行目の file_exists() は、ファイルまたはディレクトリが存在するかどうか調べる関数です。

fopen() の「r」や「r+」モードでファイルを開いて読み込む場合、ファイルが存在しない場合は、エラーになるので、最初にファイルが存在するかを確認しています。上記の場合、ファイルが存在しなければそれ以降の処理は行われません。

fgets()

ファイルが問題なく開くことができたら、fgets() を使って1行ずつファイルを読み込みます。

以下が、fgets() の構文です。

string fgets( $handle [, $length ] )

パラメータ

  • handle(resource):fopen() で取得したファイルハンドル(リソース型)を指定します。
  • length(int):読み込むバイト数です。第2引数はオプションで省略した場合は行の終わりまで読み込みます。

読み出しは、length - 1 バイト読み出したか、(返り値に含まれる) 改行文字を検出したか、EOF に達したかのいずれかが起こった時点で終了します。 (length を指定した場合、読み込むサイズは「length - 1 」バイト分になります。)

戻り値

正しく取得できた場合は取得した文字列を返し、ファイルポインタは次の行へと移動します。

ファイルポインタから読み込むデータがもうない場合や、エラーが起こるとFALSEを返します。

while($line = fgets($fp))

fgets() は次の行が存在しない場合、FALSE を返すという性質を利用して、ファイルポインタが最終行に達するまで、while ループを繰り返してファイルの内容を読み込みます。

while($line = fgets($fp)) {
  echo $line."<br>\n";
}
  • ファイルを1行読み込んだら、その1行分を $line に 格納します。
    (ファイルポインタは次の行に移動)
  • echo文 で変数に格納した $line を、改行 <br> をつけて表示します。
  • 移動したファイルポインタの位置から行末までの1行(2行目)を $line に再度代入します。
    (ファイルポインタは次の行に移動)
  • echo文 で再代入した $line を改行付きで表示...と while ループを繰り返します。
  • ファイルの終端(EOF)に達した時点で fgets() が FALSE を返すので while 文から抜けてループ終了。

feof() 関数を使って、以下のように記述することもできます。

while(!feof($fp)) {
  $line = fgets($fp);
  echo $line."<br>\n";
}

feof() 関数は、ファイルポインタがファイル終端に達しているかどうか調べる関数です。

ファイルポインタが EOF に達しているかまたはエラーの場合に TRUE 、その他の場合に FALSE を返します。

上記の場合、論理否定演算子「!」を使ってファイルポインタがファイル終端に達していない FALSE の間、ファイルをループ処理します。

ファイルの読み込み fread()

fread() はファイルをバイナリ・モードで読み込む関数です。

以下は、fread() を使用してファイルを読み込んで表示する例です。

<?php
$filename = "sample.txt";
if(file_exists($filename)){
  $fp = fopen($filename, 'rb');
  if(!$fp) {
    exit("ファイルをオープンできませんでした。");
  } else {
    $contents = fread( $fp, filesize($filename) );
    fclose($fp);
    echo $contents."<br>\n";
  }
}
?>

fgets() は1行ずつファイルを読み込みますが、fread() は、第2パラメータに読み込みたいバイト数を指定して読み込みます。

ファイルポインタは、指定したバイト数分後ろへ移動します。

また、バイト数を指定して、日本語などのマルチバイト文字を取得すると文字の途中になることがあるため、その場合は文字化けが発生します。

上記のサンプルの場合、バイト数に filesize() を使ってファイル全体のバイト数を取得して指定しています。このため、fgets() のように、各行に改行を入れるというような処理は難しいです。

以下が、fread() の構文です。

string fread( $handle , $length )

fread() は、handle が指すファイルポインタから最高 length バイト読み込みます。 以下のいずれかの条件を満たしたら、読み込みを終了します。

  • length バイトぶん読み込んだ
  • EOF (ファイルの終端) に達した

パラメータ

  • handle(resource):fopen() を使用して作成したファイルシステムポインタリソース(ファイルハンドル)。
  • length(int):最大 length バイトまで読み込む。

戻り値

読み込んだ文字列を返します。失敗した場合に FALSE を返します。

注意
バイナリとテキストファイルの形式が異なるシステム(Windows)では、fopen()の mode パラメータに 'b' を指定してファイルをオープンする必要があります。
例 fopen($filename, 'rb')

参考
ファイルの中身を文字列(変数)に格納したいだけならば、file_get_contents() を使うほうが効率的です。

<?php
$content = file_get_contents('sample.txt');
echo $content;
?>

書き込みの後に読み込む場合 rewind()

ファイルを開いて書き込んだ後に、そのファイルを読み込む場合、ファイルポインタがファイルの終端に進んでいるため、rewind() 関数でファイルポインタを先頭に戻す必要があります。

以下は、ファイルに書き込んだ後に、ファイルを読み込んで表示する例です。

<?php
$filename = "sample4.txt";
$cities = array("New York", "Barcelona", "Tokyo");
$fp = fopen($filename, 'c+b');
if(!$fp) {
  exit("ファイルを開けませんでした");
}
if(!flock($fp, LOCK_EX)) {
  exit("ファイルをロックできませんでした。");
}
foreach($cities as $value) {
  fwrite($fp, $value. "\n");
}

rewind($fp);  //ファイルポインタを先頭に戻す

while(!feof($fp)){
  echo fgets($fp) . '<br>';
}

fflush($fp);
flock($fp, LOCK_UN);
fclose($fp);
?>
New York
Barcelona
Tokyo

サンプル(アクセスカウンタ)

以下はテキストファイルを使ったアクセスカウンタの例です。

「0」とだけ入力したテキストファイルを「access_counter.txt」という名前で、このスクリプトと同じディレクトリに保存しておきます。

<?php
$ac_file = 'access_couner.txt';
$counter_lenght = 11;
$fp = fopen($ac_file, 'r+b');
if ($fp){
  if (flock($fp, LOCK_EX)){  
    $counter = fgets($fp, $counter_lenght);
    $counter++;  
    rewind($fp);  
    if (fwrite($fp,  $counter) === FALSE){
      echo 'エラー:ファイル書き込みに失敗しました。';
    }
    fflush($fp);
    flock($fp, LOCK_UN);
  }
}
fclose($fp);
echo 'アクセス数 : '.$counter;
?>
アクセス数 : 1656
  • 3行目:カウンタの桁数を10桁(11 - 1 = 10バイト)とします(10桁という値に特に理由はありません)
  • 4行目:アクセス数(最初は0)を記述したファイルを「r+b」モードで開きます。(ファイルが存在しない場合はエラーになります)
  • 5行目:ファイルが開ければ、以降の処理を実行します。
  • 6行目:ファイルをロックします(ロックできれば以降の処理を実行します)。
  • 7行目:カウンタの値を読み取り、変数 $counter に格納します。
  • 8行目:カウンタの値を1増加します。
  • 9行目:ファイルポインタを先頭に戻します。
  • 10~12行目:増加させたカウンタの値を書き込みます。(書き込みに失敗したらエラーを表示)

以下は、ユーザーがサイトにアクセスすると「アクセス日時」「アクセスした URL」「クライアントの種類」を「access_log.txt」というファイルに書き込み、それを表示するサンプルです。

<table>
<tr>
<th>アクセス日時</th>
<th>スクリプト名</th>
<th>ユーザーエージェント</th>
</tr>
<?php
$filename = 'access_log.txt';
$log = date('Y/m/d H:i:s'). "\t";
$log .= $_SERVER['SCRIPT_NAME']. "\t";
$log .= $_SERVER['HTTP_USER_AGENT'];
$fp = fopen($filename, 'a+b');
if($fp) {
  if (flock($fp, LOCK_EX)){ 
    if (fwrite($fp,  $log ."\n") === FALSE){
      echo 'エラー:ファイル書き込みに失敗しました。';
    }
    rewind($fp);
    while($line = fgets($fp, 1024)){
      $data = explode("\t", $line);
      echo "<tr>\n";
      foreach($data as $value) {
        echo "<td>" . $value . "</td>\n";
      }
      echo "</tr>\n";
    }
    fflush($fp);
    flock($fp, LOCK_UN);
  }
}
fclose($fp);    
?>
</table>
  • 1行目~6行目&33行目:表形式で表示するための HTML
  • 9行目~11行目:「アクセス日時」「アクセスした URL」「クライアントの種類」の情報をスーパーグローバル変数($_SERVER)から取得して変数 $log に格納。各値はタブ(\t)で区切る。
  • 12行目:ファイルを「a+b」(追記)モードで開く
  • 13行目:ファイルが開けたら以降を実行
  • 14行目:ファイルをロック
  • 15行目:変数 $log の値をファイルに書き込み。読み込みの際に1行ずつ読み込むので、改行(\n:環境により異なる)を付ける。
  • 18行目:ファイルポインタを先頭に戻す
  • 19行目:fgets($fp, 1024) でファイルに書かれている内容を1行ずつ取得。1024 は特に意味はないが、1行に記述されている内容より大きければ良い。(読み込みバイト数:省略可能)
  • 20行目:各行の値はタブ(\t)区切りで記述されているので、explode() でタブ文字(\t)で分割して変数 $data に格納
  • 22行目~24行目: $data には、配列が入っているので、foreach() を使って各値を出力

fopen() を使わないファイル操作

fopen() で明示的にファイルを開かなくてもファイルを読み書きできる以下のような関数があります。

fopen() を使わないファイル操作関数
関数名 概要 ロック
file() ファイル全体を読み込んで配列に格納 不可
file_get_contents() ファイルの内容を全て読み込み文字列として取得 不可
file_put_contents() 文字列をファイルに書き込む(PHP5以上) 可能
readfile() ファイルを標準出力に出力 不可
file()

file() 関数はファイルの全ての内容を取得して、1行ずつ配列に格納して返します。

「1行ずつ」とは、改行文字「\n」などのある所までが1行として扱われるという意味です。取得した内容に改行文字は付いたままとなります。

以下が構文です。

array file( $filename [, $flags [, $context ]] )

パラメータ

  • filename(string):ファイルへのパス。
  • flags(int):オプションのパラメータ flags は、以下の定数のうちのひとつ、あるいは複数の組み合わせとなります。
    • FILE_USE_INCLUDE_PATH:include_path のファイルを探します。
    • FILE_IGNORE_NEW_LINES:配列の各要素の最後に改行文字を追加しません。
    • FILE_SKIP_EMPTY_LINES:空行を読み飛ばします。

戻り値

ファイルを配列に入れて返します。 配列の各要素はファイルの各行に対応します。 失敗すると file() は FALSE を返します。

FILE_IGNORE_NEW_LINES を指定しない限り、 配列に取り込まれた各行は行末文字も含みます。 行末文字を取り除きたい場合には rtrim() を使用する必要があります。

注意:
Mac 上で作成されたファイルを読み込む際に、 PHP が行末を認識できないという問題が発生した場合、 実行時の設定オプション auto_detect_line_endings を有効にする必要が生じるかもしれません。

以下は、ファイルの内容を取得して、1行ごとに <br> を付けて表示する例です。

<?php
$contents = file('sample_text.txt');
foreach($contents as $line){
  echo $line."<br>";
}
?>
Line1: 1行目です。
Line2: 2行目です。
Line3: 3行目(最後の行)です。

以下は、HTTPを通して URL 上の HTML ソースを取得して、HTML ソースとして表示する例です。

<?php
// ファイルの内容を配列に取り込みます。
// この例ではHTTPを通してURL上のHTMLソースを取得します。
$lines = file('http://www.example.com/');

// 配列をループしてHTMLをHTMLソースとして表示し、行番号もつけます。
foreach ($lines as $line_num => $line) {
    echo "Line #<strong>{$line_num}</strong> : " . htmlspecialchars($line) . "<br>\n";
}
?>
file_get_contents()

file_get_contents() 関数はファイルの全ての内容を取得して、文字列として返します。

以下が構文です。

string file_get_contents($filename [,$use_include_path [,$context [,$offset [,$maxlen ]]]] )

この関数は file() と似ていますが、オプションの offset で指定した場所から開始し maxlen バイト分だけ ファイルの内容を文字列に読み込むことができます。

パラメータ

  • filename(string):データを読み込みたいファイルの名前。
  • use_include_path(bool):インクルードパスを使用するかどうか。(デフォルトは、FALSE)
  • context(resource):コンテキストリソース。 独自のコンテキストを使用する必要がない場合は、このパラメータに NULL を指定します。
  • offset(int):読み込みを開始するオフセット位置。 (デフォルトは、-1)
  • maxlen(int):読み込むデータの最大バイト数。 デフォルトは、ファイル終端に達するまで読み込みます。

戻り値

読み込んだデータ(文字列)を返します。失敗した場合に FALSE を返します。

以下は、テキストファイルを読み込んで表示する例です。

<?php
$contents = file_get_contents('sample_text.txt');
echo $contents;
?>
Line1: 1行目です。 Line2: 2行目です。 Line3: 3行目(最後の行)です。

以下は、テキストファイルの26バイト目から25バイト分読み込んで表示する例です。日本語(マルチバイト文字)の場合、指定したバイトが文字の途中に当たると文字化けします。

<?php
$section = file_get_contents('sample_text.txt', FALSE, NULL, 25, 25);
echo $section;
?>
Line2: 2行目です。

以下は、あるウェブサイトのホームページのソースの取得と出力の例です。

<?php
$homepage = file_get_contents('http://www.example.com/');
echo htmlspecialchars($homepage);
?>
<!doctype html> <html> <head> <title>Example Domain</title> <meta charset="utf-8" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <style type="text/css"> body { background-color: #f0f0f2; margin: 0; padding: 0; font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; } div { width: 600px; margin: 5em auto; padding: 50px; background-color: #fff; border-radius: 1em; } a:link, a:visited { color: #38488f; text-decoration: none; } @media (max-width: 700px) { body { background-color: #fff; } div { width: auto; margin: 0 auto; border-radius: 0; padding: 1em; } } </style> </head> <body> <div> <h1>Example Domain</h1> <p>This domain is established to be used for illustrative examples in documents. You may use this domain in examples without prior coordination or asking for permission.</p> <p><a href="http://www.iana.org/domains/example">More information...</a></p> </div> </body> </html>
file_put_contents()

file_put_contents() 関数は、fopen()、fwrite()、 fclose() を続けて実行するのと同じです。

指定したファイルが存在しない場合はファイルを作成します。 存在する場合はそのファイルを上書きします。ただし FILE_APPEND フラグが設定されている場合は追記になります。

また、オプションの指定で書き込み処理中に、ファイルに対する排他ロックを行うことができます。

以下が構文です。

int file_put_contents( $filename , $data [, $flags ] )

パラメータ

  • filename(string):データを書き込むファイルへのパス。
  • data(mixed):書き込むデータ。文字列, 配列 もしくは ストリーム リソースのいずれかを指定可能です。
  • flags(int):flags の値は、以下のフラグを組み合わせたものとなります 組み合わせる際には、論理 OR (|) 演算子で連結します。
    • FILE_USE_INCLUDE_PATH :filename をインクルードディレクトリから探します。
    • FILE_APPEND :filename がすでに存在する場合に、 データをファイルに上書きするするのではなく追記します。
    • LOCK_EX :書き込み処理中に、ファイルに対する排他ロックを確保します。

戻り値

この関数はファイルに書き込まれたバイト数を返します。 但し、失敗した場合には FALSE を返します。

この関数は論理値 FALSE を返す可能性がありますが、FALSE として評価される値を返す可能性もあるので、この関数の返り値を調べるには ===演算子を使用する必要があります。

以下は、既存の内容を取得して、新しい内容を追加して書き込む例です。

<?php
$file = 'fruits.txt';
// ファイルをオープンして既存のコンテンツを取得します
$contents = file_get_contents($file);
// 新しい内容をファイルに追加します
$contents .= "Apple\n";
// 結果をファイルに書き出します
file_put_contents($file, $contents);
?>

以下は、オプションのフラグで、追記(FILE_APPEND)と排他ロック(LOCK_EX)を指定して書き込む例です。

<?php
$file = 'fruits.txt';
$fruit = "Strawberry\n";
//ファイルに書き込み
file_put_contents($file, $fruit, FILE_APPEND | LOCK_EX);
echo file_get_contents($file);
?>

fopen()、fwrite()、 fclose() を続けて実行する以下と同じことになります。

<?php
$file = 'fruits.txt';
$fp = fopen($file, 'a+b');  //ファイルをオープン
flock($fp, LOCK_EX);  //ファイルをロック
fwrite($fp, "Strawberry\n");  //ファイルに書き込み
fflush($fp);  // 出力をフラッシュ
flock($fp, LOCK_UN);  // ロックを解放
fclose($fp);  //ファイルをクローズ
echo file_get_contents($file);
?>
readfile()

readfile() 関数は指定したファイル内容を全て読み込んで標準出力に出力します。標準出力とは Web サーバで PHP を動作させている場合はブラウザになります。

以下が構文です。

int readfile( $filename [, $use_include_path] )

パラメータ

  • filename(string): 読み込もうとするファイルの名前。
  • use_include_path(bool):これにTRUEを設定することにより、 include_path のファイルの検索も行うことができます。

fopen wrappers が有効(allow_url_fopen=On)の場合、この関数のファイル名として URL を使用することができます。

戻り値

ファイルから読み込んだバイト数を返します。エラーが起こると FALSEを返し、また@readfile()という名前でコールされない限り、 エラーメッセージが表示されます。(エラー制御演算子 @ でエラーの出力を抑える事ができます。)

以下は、テキストファイルを表示する例です。

<?php
readfile("fruits.txt");
?>

ファイル関連の関数

以下は、ファイル関連の関数についてです。

file_exists() /is_file() / is_dir()

file_exists() は、ファイルまたはディレクトリが存在するかどうか調べる関数です。

以下が構文です。

bool file_exists( $filename )

パラメータ

  • filename(string):ファイルあるいはディレクトリへのパス。

戻り値

指定したファイルまたはディレクトリが存在すれば TRUE を返し、そうでなければ FALSE を返します。

注意: この関数の結果は キャッシュされます。(clearstatcache() を参照)

is_file()

is_file() は、指定したファイルが通常のファイルかどうかを調べる関数です。

以下が構文です。

bool is_file( $filename )

パラメータ

  • filename(string):ファイルへのパス。

戻り値

ファイルが存在し、かつそれが通常のファイルである場合に TRUE、 それ以外の場合に FALSE を返します。

注意: この関数の結果は キャッシュされます。(clearstatcache() を参照)

is_dir()

is_dir() は、指定したファイルがディレクトリかどうかを調べる関数です。

以下が構文です。

bool is_dir( $filename )

パラメータ

  • filename(string):ディレクトリへのパス。

戻り値

ファイルが存在して、かつそれがディレクトリであれば TRUE、それ以外の場合は FALSE を返します。

注意: この関数の結果は キャッシュされます。(clearstatcache() を参照)

feof()

feof() 関数は、ファイルポインタがファイル終端に達しているかどうか調べる関数です。以下が構文です。

bool feof( $handle )

パラメータ

  • handle(resource):fopen() で取得したファイルハンドル(リソース型)を指定します。

戻り値

ファイルポインタが EOF に達しているかまたはエラーの場合に TRUE 、その他の場合に FALSE を返します。

filesize()

ファイルのサイズを取得するには filesize() 関数を使用します。

以下が、構文でパラメータにファイル名(ファイルのパス)を指定して、ファイルサイズを取得します。エラーの場合は FALSE を返します (また E_WARNING レベルのエラーを発生させます) 。

int filesize( $filename )

パラメータ

  • filename(string):ファイルへのパス。

注意: この関数の結果は キャッシュされます。(clearstatcache() を参照)

rewind()

以下は、rewind() 関数の構文です。

bool rewind( $handle )

ファイルポインタの位置を先頭に戻します。

パラメータ

  • handle(resource):fopen() を使用した際に、返されるファイルハンドル。

戻り値

成功した場合に TRUE を、失敗した場合に FALSE を返します。

fileatime() / filemtime()

fileatime() 関数は、ファイルの最終アクセス(access)時刻を取得する関数です。以下が構文です。

int fileatime( $filename )

指定したファイルの最終アクセス時刻を取得します。

パラメータ

  • $filename(string ):ファイルへのパス。

戻り値

ファイルの最終アクセス時刻を返し、失敗した場合に FALSE を返します。 時間は Unix タイムスタンプとして返されます。

この関数の結果は date() 等で使用できます。

<?php
echo date("Y/m/d H:i:s", fileatime("sample.txt"));
?>

filemtime()

filemtime() 関数は、ファイルの更新(modify)時刻を取得する関数です。以下が構文です。

int filemtime( $filename )

この関数は、ファイルのブロックデータが書き込まれた時間を返します。 これは、ファイルの内容が変更された際の時間です。

パラメータ

  • $filename(string ):ファイルへのパス。

戻り値

ファイルの最終更新時刻を返し、失敗した場合に FALSE を返します。 時間は Unix タイムスタンプとして返され、そのまま date () に渡す事ができます。

<?php
echo date("Y/m/d H:i:s", filemtime("sample.txt"));
?>

キャッシュを解除する例

ブラウザのキャッシュを設定後、ファイルに変更があった場合に、その変更を反映させる方法としてファイル名の末尾にクエリ文字列を付加する方法があります。(関連ページ:キャッシュの制御

以下は filemtime() を使ってキャッシュを解除させる例です。

ファイルに変更がある度に、filemtime() によるタイムスタンプが付くのでブラウザはそのクエリ(「?」の文字+タイムスタンプ)のついた URL をまだ取得していないファイルと認識し、キャッシュは読み込まずにサーバーからファイルを取得します。

<?php
echo '<link rel="stylesheet" href="../css/style.css?' . filemtime('../css/style.css') . '">';
?> 

以下は、上記による出力例です。

<link rel="stylesheet" href="../css/style.css?1530456799"> 

更新日時 getlastmod()

現在のファイルの更新日時を取得するには getlastmod() 関数を使用します。

以下が構文です。

int getlastmod ( void )

パラメータ

  • なし

戻り値

現在のページの最終更新時刻を返し、失敗した場合に FALSE を返します。 時間は Unix タイムスタンプとして返されそのまま date () に渡す事ができます。

別のファイルの更新日時を取得する場合は、 filemtime() を使用します。

以下は、現在のページの最終更新日時を表示する例です。日付のフォーマットは、date() の第1パラメータで指定します。

<?php
echo "このページの最終更新日:" . date( "Y/m/d H:i", getlastmod() );
?>

このページの最終更新日:2018/07/03 21:11

また、同じ内容を全てのページに記述するのは、効率的ではないので、以下を例えば last_modified.php というファイル名で保存して、各ページから include_once() などを使って読み込むようにすると管理が楽になります。

以下では、終了タグ「?>」を省略しています。(関連項目:終了タグの省略

/*last_modified.php*/
<?php
echo "<p id='last_modified'>更新日:" . date( 'Y年m月d日', getlastmod() ) . "</p>";

各ページからは以下のように include_once() などを使って読み込むようにします。

<?php include_once("last_modified.php"); ?>

または、以下のように $_SERVER['DOCUMENT_ROOT'] を使って読み込むファイルをドキュメントルート(ドメイン直下)から指定すれば、階層(ディレクトリ)ごとに記述を変える必要がないので便利です。「path」はドキュメントルートからファイルまでのパスを指定します。

<?php include_once($_SERVER['DOCUMENT_ROOT']. "/path/last_modified.php"); ?>  

filemtime() のパラメータに現在のページを指定すれば、現在のページの最終更新時刻を取得できます。

現在のページは「basename()」を使って取得できます。

<?php
echo "更新日:".date( 'Y年m月d日', filemtime(basename(__FILE__)) );
?>

更新日:2018年07月03日

fstat() / stat()

ファイルに関する情報をまとめて取得する場合は fstat() 関数stat() 関数を使用します。

  • fstat() 関数は、オープンしたファイルポインタからファイルに関する情報を取得します。
  • stat() 関数は、ファイル名を指定してファイルに関する情報を取得します。

以下は、fstat() 関数の構文です。

array fstat( $handle )

パラメータ

  • handle(resource):fopen() を使用して作成したファイルシステムポインタリソース。

戻り値

ファイルの統計情報の配列を返します。

以下は、stat() 関数の構文です。

array stat ( $filename )

パラメータ

  • filename(string):ファイルへのパス。

戻り値

ファイルの統計情報の配列を返します。

stat() と fstat() の結果(戻り値)のフォーマット
数値 連想配列 説明
0 dev デバイス番号
1 ino inode 番号(*)
2 mode inode プロテクトモード
3 nlink リンク数
4 uid 所有者のユーザー ID(*)
5 gid 所有者のグループ ID(*)
6 rdev inode デバイス の場合、デバイスの種類
7 size バイト単位のサイズ
8 atime 最終アクセス時間 (Unix タイムスタンプ)
9 mtime 最終修正時間 (Unix タイムスタンプ)
10 ctime 最終 inode 変更時間 (Unix タイムスタンプ)
11 blksize ファイル IO のブロックサイズ(**)
12 blocks 512 バイトのブロックの確保数(**)
  • * Windows では常に 0 となります。
  • ** st_blksize タイプをサポートするシステムでのみ有効です。 その他のシステム(例えば Windows)では -1 を返します。

以下は、stat() とマジック定数「__FILE__」を使って現在のファイルの情報を出力する例です。

通常の配列(数値の添え字)と連想配列の両方でファイルの情報が出力されます。

<?php
var_dump( stat(__FILE__) );
?>
array(26) {
  [0]=>
  int(2052)
  [1]=>
  int(152915898)
  [2]=>
  int(33188)
  [3]=>
  int(1)
  [4]=>
  int(1685)
  [5]=>
  int(1691)
  [6]=>
  int(0)
  [7]=>
  int(149102)
  [8]=>
  int(1532326109)
  [9]=>
  int(1530652288)
  [10]=>
  int(1530652288)
  [11]=>
  int(4096)
  [12]=>
  int(296)
  ["dev"]=>
  int(2052)
  ["ino"]=>
  int(152915898)
  ["mode"]=>
  int(33188)
  ["nlink"]=>
  int(1)
  ["uid"]=>
  int(1685)
  ["gid"]=>
  int(1691)
  ["rdev"]=>
  int(0)
  ["size"]=>
  int(149102)
  ["atime"]=>
  int(1532326109)
  ["mtime"]=>
  int(1530652288)
  ["ctime"]=>
  int(1530652288)
  ["blksize"]=>
  int(4096)
  ["blocks"]=>
  int(296)
}

以下は、fstat() を使って「ファイルサイズ」と「アクセス日時」と「更新日時」を表示する例です。

<?php
$fp = fopen('sample.txt', 'r');
$fstat = fstat($fp);
fclose($fp);
echo "ファイルサイズ : ". $fstat['size'] . " byte <br>";
//filesize() をコールするのと同じ
echo "アクセス日時 : ". date("Y/m/d H:i:s", $fstat['atime']) . "<br>";
//fileatime() をコールするのと同じ
echo "更新日時 : ". date("Y/m/d H:i:s", $fstat['mtime'] ) . "<br>";
//filemtime() をコールするのと同じ
?>
ファイルサイズ : 51748 byte
アクセス日時 : 2018/07/22 16:49:15
更新日時 : 2018/07/23 08:01:27

copy()

copy() 関数は、ファイルをコピーする関数です。以下が構文です。

bool copy( $source , $dest )

ファイル source を dest にコピーします。

ファイルを移動したいならば、rename() 関数を使用します。

パラメータ

  • source(string):コピー元ファイルへのパス。
  • dest(string):コピー先のパス。dest が URL の場合、 既存ファイルへの上書きをラッパーがサポートしていない場合にはコピーが失敗します。

警告
コピー先のファイルが既に存在する場合、上書きされます。

戻り値

成功した場合に TRUE を、失敗した場合に FALSE を返します。

以下は、example.txt を example.txt.bak という名前でコピーする例です。コピーに失敗した場合は、メッセージを表示します。

<?php
$file = 'example.txt';
$newfile = 'example.txt.bak';

if (!copy($file, $newfile)) {
    echo "failed to copy $file...\n";
}
?>    

以下は、すでに同じ名前のファイルがある場合は、メッセージを表示する例です。

<?php
$file = 'sample.txt';
$newfile = 'newfile.txt';
if(file_exists($newfile)) {
  echo "すでに同じ名前のファイルが存在します。";
}else{
  if (copy($file, $newfile)) {
    echo "コピーしました。";
  }else{
    echo "コピーに失敗しました。";
  }
}
?>    

rename()

rename() 関数は、ファイルの名前を変更(または、ファイルを移動)する関数です。以下が構文です。

bool rename( $oldname , $newname )

oldname を newname にリネームし、必要ならディレクトリを移動しようと試みます。 newname が存在する場合は、上書きします。

パラメータ

  • oldname(string):変更前の名前
  • newname(string):変更後の名前。

戻り値

成功した場合に TRUE を、失敗した場合に FALSE を返します。

<?php
//名前の変更
rename( "example.txt" , "new_example.txt" );
//移動
rename( "test.txt", "../sample/test.txt" );
?>

パス関連

以下はパス関連の関数などについてです。

URL や ホスト名を取得するには、スーパーグローバル変数「$_SERVER」を使う方法もあります。
(関連項目:$_SERVER

マジック定数

PHP のマジック定数には、ファイル名やディレクトリ名を返してくれるものがあります。

  • __FILE__ :ファイルのフルパスとファイル名
  • __DIR__ :そのファイルの存在するディレクトリ。include の中で使用すると、 インクルードされるファイルの存在するディレクトリを返します。 これは dirname(__FILE__) と同じ意味です。(Ver5.3.0より)
<?php
echo __FILE__ ."<br>";
echo __DIR__ ."<br>";
?>
/home/username/public_html/webdesignleaves.com/pr/php/php_basic_04.php
/home/username/public_html/webdesignleaves.com/pr/php

dirname()

dirname() 関数は、親ディレクトリのパスを返します。 以下が構文です。

string dirname( $path [, $levels ] )

パラメータ

  • path(string):パス。
    Windows では、スラッシュ(/)とバックスラッシュ (\)の両方がディレクトリ区切り文字として使われます。 その他の環境ではスラッシュ(/)になります。
  • levels(int):PHP 7.0.0 以降で使用可能。それ以前のバージョンではエラー(警告)になります。 親ディレクトリをどこまでさかのぼるかを指定(デフォルトは 1)。正の整数でなければいけません。

戻り値

親ディレクトリのパスを返します。 path にスラッシュが無い場合は、 カレントディレクトリを示すドット ('.') を返します。

以下はサンプルです。

<?php
echo dirname(__FILE__)  ."<br>";  //__DIR__ と同じこと
echo dirname("/usr/local/lib") ."<br>";
?>
/home/username/public_html/webdesignleaves.com/pr/php
/usr/local

以下は絶対 URL を出力するサンプルです。

  • $_SERVER['HTTP_HOST'] →ホスト名
  • dirname($_SERVER['PHP_SELF'])→現在のディレクトリ
<?php
$filename = 'index.php';
echo $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . '/'.  $filename;
?>
webdesignleaves.com/pr/php/index.php

注意:
dirname() は、入力文字列を単純にそのまま処理します。 実際のファイルシステムを確認したりすることはありません。

注意:
dirname() はロケールに依存します。 マルチバイト文字を含むパスで正しい結果を得るには、それと一致するロケールを setlocale() で設定しておかなければなりません。

realpath()

realpath() 関数は、絶対パス名を返します。 以下が構文です。

string realpath ( string $path )

パラメータ

  • path(string):調べたいパス。

注意:
path の指定は必須ですが、空白や NULL を指定することもできます。 その場合はカレントディレクトリを指定したものとみなします。

戻り値

成功した場合は正規化した絶対パス名を返します。 返されるパスはシンボリックリンクや「/./」「/../」要素を含みません。 パスの末尾の区切り文字 (\ や / など) は削除されます。

realpath() は、ファイルが存在しないなどの失敗時に FALSE を返します。

以下はサンプルです。

<?php
echo realpath(__FILE__)."<br>";
echo realpath(__DIR__)."<br>";
echo realpath("")."<br>";
echo realpath(getcwd())."<br>";
echo realpath(__DIR__ . "/../jquery/index.html")."<br>";
?>
/home/username/public_html/webdesignleaves.com/pr/php/php_basic_04.php
/home/username/public_html/webdesignleaves.com/pr/php
/home/username/public_html/webdesignleaves.com/pr/php
/home/username/public_html/webdesignleaves.com/pr/php
/home/username/public_html/webdesignleaves.com/pr/jquery/index.html

getcwd() はカレントのワーキングディレクトリを取得します。

basename()

basename() はパスの最後にある名前の部分を返します。 以下が構文です。

string basename( $path [, $suffix ] )

パラメータ

  • path(string): パス。
    Windows では、スラッシュ(/) とバックスラッシュ (\) の両方がディレクトリ区切り文字として使われます。 その他の環境ではスラッシュ(/)になります。
  • suffix(string):名前の部分が suffix で終了する場合、 この部分もカットされます。

戻り値

指定した path のベース名を返します。

注意:
basename() は、入力文字列を単純にそのまま処理します。 実際のファイルシステムを確認したりすることはありません。

注意:
basename() はロケールに依存します。 マルチバイト文字を含むパスで正しい結果を得るには、それと一致するロケールを setlocale() で設定しておかなければなりません。

以下はサンプルです。

<?php
echo basename(__FILE__)."<br>";
echo basename(__FILE__, '.php');
?>
php_basic_04.php
php_basic_04

pathinfo()

pathinfo() はファイルパスに関する情報を返します。 以下が構文です。

mixed pathinfo( $path [, $options ] )

パラメータ

  • path(string):調べたいパス。
  • options(int):指定する場合は、どの要素を返すのかを以下の定数のいずれかで指定します。options を省略した場合はすべての要素を返します。
    • PATHINFO_DIRNAME
    • PATHINFO_BASENAME
    • PATHINFO_EXTENSION
    • PATHINFO_FILENAME

戻り値

options パラメータを渡さなかった場合は、次の要素を含む連想配列を返します。 dirname、basename、 extension (存在すれば)、そして filename。

以下はサンプルです。

<?php
$path_parts = pathinfo(realpath(__FILE__));

echo "dirname : " . $path_parts['dirname'], "<br>";
echo "basename : " . $path_parts['basename'], "<br>";
echo "extension: " . $path_parts['extension'], "<br>";
echo "filename: " . $path_parts['filename'], "<br>"; // PHP 5.2.0 以降
?>
dirname : /home/username/public_html/webdesignleaves.com/pr/php
basename : php_basic_04.php
extension: php
filename: php_basic_04

parse_url()

parse_url() はURL を解釈し、その構成要素を返します。

この関数は、指定された URL が有効かどうかを調べるためのものではなく、単に URL を要素に分解するだけのものです。

不完全な URL であっても受け入れられますし、 そのような場合でも parse_url() は可能な限り 正しく解析しようとします。

以下が構文です。

mixed parse_url( $url [, $component ] )

この関数は、URL の様々な構成要素のうち特定できるものに関して 連想配列にして返します。

パラメータ

  • url(string):パースする URL。無効な文字は _ に置換されます。
  • component(int): 以下のいずれかを指定し、 特定の URL コンポーネントのみを文字列 (PHP_URL_PORT を指定した場合だけは整数値) で取得するようにします。
    • PHP_URL_SCHEME
    • PHP_URL_HOST
    • PHP_URL_PORT
    • PHP_URL_USER
    • PHP_URL_PASS
    • PHP_URL_PATH
    • PHP_URL_QUERY
    • PHP_URL_FRAGMENT

戻り値

第2パラメータの component を省略した場合は、連想配列を返します この配列に含まれる可能性のある要素は次のとおりです。

  • scheme - 例: http
  • host
  • port
  • user
  • pass
  • path
  • query - クエスチョンマーク ? 以降
  • fragment - ハッシュマーク # 以降

component が指定されている場合、 parse_url() は配列ではなく文字列 (PHP_URL_PORT の場合は整数値) を返します。 要求したコンポーネントが指定した URL の中にない場合は NULL を返します。

また、完全におかしな形式の URL については、parse_url() は FALSE を返します。

以下はサンプルです。

<?php
$url = 'http://www.example.com:12080/test/?arg=value#anchor';
echo "URL_SCHEME : " . parse_url($url, PHP_URL_SCHEME). "<br>";
echo "URL_USER : " . parse_url($url, PHP_URL_USER). "<br>";
echo "URL_PASS : " . parse_url($url, PHP_URL_PASS). "<br>";
echo "URL_HOST : " . parse_url($url, PHP_URL_HOST). "<br>";
echo "URL_PORT : " . parse_url($url, PHP_URL_PORT). "<br>";
echo "URL_PATH : " . parse_url($url, PHP_URL_PATH). "<br>";
echo "URL_QUERY : " . parse_url($url, PHP_URL_QUERY). "<br>";
echo "URL_FRAGMENT : " . parse_url($url, PHP_URL_FRAGMENT). "<br>";
?>
URL_SCHEME : http
URL_USER :
URL_PASS :
URL_HOST : www.example.com
URL_PORT : 12080
URL_PATH : /test/
URL_QUERY : arg=value
URL_FRAGMENT : anchor

$_SERVER['DOCUMENT_ROOT']

環境変数 $_SERVER['DOCUMENT_ROOT'] は、ドキュメントルート(ドメイン直下)のパスを返してくれます。サーバーのコンフィグレーションファイル(httpd.conf)で定義されています。

<?php
echo $_SERVER['DOCUMENT_ROOT'];
?>

/home/username/public_html/webdesignleaves.com

ファイルの読み込みなどの場合、$_SERVER['DOCUMENT_ROOT'] はドキュメントルートのパスを返してくれるので、インクルードしたいファイルのドキュメントルートからのパスを付けて記述します。読み込む階層が異なっていてもパスを変更する必要がないので便利です。

<?php include_once($_SERVER['DOCUMENT_ROOT'] . "/path/file.php"); ?> 

$_SERVER['DOCUMENT_ROOT'] は httpd.conf で定義されています。以下は XAMPP の httpd.conf(C:\xampp\apache\conf)の240行目辺りに記述されている定義例です。

# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
DocumentRoot "C:/xampp/htdocs"

画像ファイル

画像サイズの取得 getimagesize()

getimagesize() 関数は、画像サイズを含む画像に関する情報を取得します。以下が構文です。

array getimagesize( $filename [, &$imageinfo ] )/pre>

getimagesize() は、画像のサイズ、画像の種類、img タグで使用できる高さ/幅を表す文字列を返します。また、 imageinfo パラメータで追加情報を返します。

パラメータ

  • filename(string):このパラメータは、情報を取得したいファイルの名前を指定します。 ローカルファイルへの参照、あるいは (設定で許可されているなら) ストリームを用いたリモートファイルへの参照を指定できます。
  • imageinfo(array):オプションのパラメータで、 画像ファイルから何らかの拡張情報を引き出すことが可能です。

戻り値

最大 7 つの要素からなる配列を返します。画像の形式によっては、 channels や bits , mime は含まれないことがあります。

  • 0 番目および 1 番目の要素は、それぞれ画像の幅と高さを表します。
  • 2 番目の要素は IMAGETYPE_XXX constants 定数のひとつで、 画像の形式を表します。
  • 3 番目の要素は IMG タグで直接利用できる文字列 height="yyy" width="xxx" です。
  • bits は個々の色のビット数です。
  • channels は RGB 画像の場合は3、CMYK 画像の場合は4になります。
  • mime は画像の MIME タイプに一致します。この情報は 画像とともに正しい HTTP Content-type ヘッダを転送するために使用できます。

失敗した場合には FALSE を返します。

注意:
形式によっては、画像を含まないものや複数の画像を含むものがあります。 これらの場合、getimagesize() は画像のサイズを適切に決定することができません。このような場合、 getimagesize() が返す幅と高さはいずれもゼロとなります。

エラー / 例外:
もし filename のイメージにアクセスできない場合、 getimagesize() は FALSE を返し、E_WARNING レベルのエラーを発生させます。 読み込み時にエラーが発生した場合は、 getimagesize() は E_NOTICE レベルのエラーを発生させます。

以下は、画像ファイルを指定して、その情報を表示する例です。

<?php
$filename = "../images/photo_01.jpg";
$imageinfo = getimagesize($filename);
echo "<table>\n";
echo "<tr><td>ファイル名</td>";
echo "<td>". $filename . "</td></tr>\n";
echo "<tr><td>幅</td>";
echo "<td>". $imageinfo[0] . "</td></tr>\n";
echo "<tr><td>高さ</td>";
echo "<td>". $imageinfo[1] . "</td></tr>\n";
echo "<tr><td>種類(1: GIF, 2: JPG, 3: PNG, 4: SWF)</td>";
echo "<td>". $imageinfo[2] . "</td></tr>\n";
echo "<tr><td>高さ/幅を表す文字列</td>";
echo "<td>". $imageinfo[3] . "</td></tr>\n";
//以降は PHP 4.3.0 から
echo "<tr><td>bits(色のビット数)</td>";
echo "<td>". $imageinfo['bits'] . "</td></tr>\n";
echo "<tr><td>channels(3: RGB, 4: CMYK)</td>";
echo "<td>". $imageinfo['channels'] . "</td></tr>\n";
echo "<tr><td>MIME</td>";
echo "<td>". $imageinfo['mime'] . "</td></tr>\n";
echo "</table>\n";

echo "<p><img src='" .$filename . "' alt='photo' /></p>";
?>
ファイル名 $filename../images/photo_01.jpg
幅 $imageinfo[0]400
高さ $imageinfo[1]266
種類(1: GIF, 2: JPG, 3: PNG, 4: SWF) $imageinfo[2]2
高さ/幅を表す文字列 $imageinfo[3]width="400" height="266"
bits(色のビット数) $imageinfo['bits']8
channels(3: RGB, 4: CMYK) $imageinfo['channels']3
MIME タイプ $imageinfo['mime']image/jpeg

photo

この例では、取得した配列 $imageinfo から、幅の場合は $imageinfo[0] のようにして取り出しています。

以下は、list() を使って変数に代入する例です。

<?php
$filename = "../images/photo_01.jpg";
$imageinfo = getimagesize($filename);
list($width, $height, $type, $size) = $imageinfo;
echo "幅 : ". $width ."<br>";
echo "高さ : ". $height."<br>";
echo "種類 : ". $type."<br>";
echo "サイズ : ". $size."<br>";
?>
幅 : 400
高さ : 266
種類 : 2
サイズ : width="400" height="266"

list() は、連想配列ではそのままでは使えないので、array_values() 関数を使って連想配列の値を取得して利用します。

<?php
$filename = "../images/photo_01.jpg";
$imageinfo = getimagesize($filename);
list($width, $height, $type, $size, $bits, $channels, $mime) = array_values($imageinfo);
echo "幅 : ". $width ."<br>";
echo "高さ : ". $height."<br>";
echo "種類 : ". $type."<br>";
echo "サイズ : ". $size."<br>";
echo "bits : ". $bits."<br>";
echo "channels : ". $channels."<br>";
echo "MIME : ". $mime."<br>";
?>
幅 : 400
高さ : 266
種類 : 2
サイズ : width="400" height="266"
bits : 8
channels : 3
MIME : image/jpeg

ディレクトリ内の画像を一覧表示

以下は、dir() でディレクトリ内のファイルを取得し、getimagesize() で画像かどうかを判定して一覧表示する例です。

  • dir() で指定したディレクトリオブジェクトの read() メソッドでファイルを1つずつ取り出します。
  • ディレクトリオブジェクトの path プロパティから取得したディレクトリのパスにファイル名を加えて、ファイルのパス($path)とします。
  • getimagesize() で画像かどうかの判定をします(画像でない場合は FALSE が返る)。
  • また、画像以外のファイルやフォルダがあるとエラーが出力されるので、@(エラー制御演算子)を使ってエラーを出力しないようにしています。
  • 画像の場合は、リンク(a 要素)を付けて画像をサムネイル(width="80")表示します。
  • ディレクトリオブジェクトの close() メソッドでディレクトリを閉じます。
<?php
$dir_name = "../images/jquery/SlideShow";
if ($dir = dir($dir_name)) {
  while(FALSE !== ($filename = $dir->read())) {
    $path = $dir->path . '/' . $filename;
    if(@getimagesize($path)) {
      echo '<a href="' . $path . '" target="_blank">';
      echo '<img src="' . $path . '" width="80" alt="Photo" style="margin:5px">';
      echo "</a>\n";
    }
  }
}
$dir->close();
?>
Photo Photo Photo Photo Photo Photo

以下は同じことを、opendir() を使って行う例です。

<?php
$dir_name = "../images/jquery/SlideShow";
if ($handle = opendir($dir_name)) {
  while (false !== ($filename = readdir($handle))) {
    $path = $dir_name . '/' . $filename;
    if(@getimagesize($path)) {
      echo '<a href="' . $path . '" target="_blank">';
      echo '<img src="' . $path . '" width="80" alt="Photo" style="margin:5px">';
      echo "</a>\n";
    }
  } 
  closedir($handle);
}

以下は同じことを、scandir() を使って行う例です。

<?php
$dir_name = "../images/jquery/SlideShow";
if($file_arrays = scandir($dir_name)) {
  foreach($file_arrays as $filename) {
    $path = $dir_name . '/' . $filename;
    if(@getimagesize($path)) {
      echo '<a href="' . $path . '" target="_blank">';
      echo '<img src="' . $path . '" width="80" alt="Photo" style="margin:5px">';
      echo "</a>\n";
    }
  }
}
?>