Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】STREAM_MKDIR_RECURSIVE定数の使い方

STREAM_MKDIR_RECURSIVE定数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

STREAM_MKDIR_RECURSIVE定数は、ファイルシステム上に新しいディレクトリを作成する際に、その作成処理の振る舞いを指定するための定数です。この定数は、PHPでディレクトリを作成する関数、例えば mkdir()stream_mkdir() などで使用されるオプションの一部として利用されます。

通常、mkdir()関数で存在しない親ディレクトリを含むパスを指定した場合、その親ディレクトリが存在しないとエラーになりますが、STREAM_MKDIR_RECURSIVE定数をオプションとして指定することで、その挙動を変更できます。具体的には、この定数を指定すると、作成しようとするディレクトリパスの途中に、まだ存在しない親ディレクトリがあったとしても、それらの中間ディレクトリもすべて自動的に作成する「再帰的な作成」を有効にします。

例えば、「/var/www/html/project/uploads」というパスで「project」や「uploads」ディレクトリが存在しない場合、通常は「project」が存在しないためエラーになります。しかし、STREAM_MKDIR_RECURSIVE定数を指定して実行すると、「project」ディレクトリが作成され、その中に「uploads」ディレクトリが作成されます。

この機能は、ファイルのアップロード先や一時ファイルの保存場所など、動的に深い階層のディレクトリを作成する必要がある場合に非常に便利です。開発者が一つずつ親ディレクトリの存在を確認したり、手動で作成したりする手間を省き、より安全で効率的なコードを書くのに役立ちます。これにより、ファイルシステム操作の信頼性と簡潔さが向上します。

構文(syntax)

1mkdir('/path/to/new/directory/recursively', 0777, STREAM_MKDIR_RECURSIVE);

引数(parameters)

引数なし

引数はありません

戻り値(return)

戻り値なし

戻り値はありません

サンプルコード

PHP: STREAM_MKDIR_RECURSIVE を使ったストリームディレクトリ作成

1<?php
2
3/**
4 * STREAM_MKDIR_RECURSIVE 定数が示す機能をストリームコンテキストを通じてディレクトリ作成するサンプル。
5 *
6 * この関数は、多階層のディレクトリを再帰的に作成し、stream_context_create を使って
7 * その動作を制御する方法を示します。STREAM_MKDIR_RECURSIVE 定数は、
8 * ストリームコンテキストの 'mkdir' オプションにおける 'recursive' フラグの内部的な意味合いを持ちます。
9 *
10 * @param string $path 作成するディレクトリのパス(例: 'temp_recursive_dir/sub/directory')
11 * @return void
12 */
13function demonstrationStreamMkdirRecursive(string $path): void
14{
15    // 作成する多階層のディレクトリパス
16    $targetPath = $path;
17
18    echo "--- ディレクトリ作成の準備 ---\n";
19    echo "対象パス: {$targetPath}\n";
20
21    // STREAM_MKDIR_RECURSIVE 定数が示す「再帰的なディレクトリ作成」の機能を
22    // ストリームコンテキストを通じて実現するためのオプションを設定します。
23    // 'mkdir' コンテキストの 'recursive' オプションを true に設定することで、
24    // 中間ディレクトリも自動的に作成されます。
25    $options = [
26        'mkdir' => [
27            'recursive' => true, // このオプションが STREAM_MKDIR_RECURSIVE の機能に対応します
28        ],
29    ];
30
31    // ストリームコンテキストを作成します。
32    // これをファイルシステム操作関数に渡すことで、特定のオプションを適用できます。
33    $context = stream_context_create($options);
34
35    // mkdir() 関数を使ってディレクトリを作成します。
36    // 第4引数にストリームコンテキストを渡すことで、設定したオプションが適用されます。
37    // 第3引数の $recursive は false に設定していますが、コンテキストオプションの 'recursive' が優先されます。
38    // 実際には、mkdir($targetPath, 0777, true) とほぼ同等ですが、
39    // stream_context_create の利用方法を示すための例です。
40    echo "ストリームコンテキストを使用してディレクトリを作成中...\n";
41    if (mkdir($targetPath, 0777, false, $context)) {
42        echo "成功: ディレクトリ '{$targetPath}' を再帰的に作成しました。\n";
43
44        // 確認のために作成したディレクトリ内にファイルを置いてみる
45        $testFilePath = $targetPath . '/test_file.txt';
46        file_put_contents($testFilePath, 'This is a test file created in the new directory.');
47        echo "確認用ファイル '{$testFilePath}' を作成しました。\n";
48    } else {
49        echo "失敗: ディレクトリ '{$targetPath}' の作成に失敗しました。\n";
50        // 失敗した場合はここで処理を終了
51        return;
52    }
53
54    echo "\n--- クリーンアップ ---\n";
55
56    // クリーンアップ処理を開始します。
57    // 作成したディレクトリとファイルを削除します。
58    // rmdir は空でないディレクトリを削除できないため、再帰的に削除します。
59
60    // 作成したファイルを削除
61    if (isset($testFilePath) && file_exists($testFilePath)) {
62        unlink($testFilePath);
63        echo "ファイル '{$testFilePath}' を削除しました。\n";
64    }
65
66    // 作成された最上位のディレクトリを特定します。
67    // 例: 'temp_recursive_dir/sub/directory' から 'temp_recursive_dir' を取得
68    $pathSegments = explode(DIRECTORY_SEPARATOR, str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $path));
69    $topLevelDirToClean = $pathSegments[0];
70    if ($topLevelDirToClean === '.' && count($pathSegments) > 1) { // パスが `./` で始まる場合
71        $topLevelDirToClean = $pathSegments[1];
72    }
73    // 空文字の場合はカレントディレクトリとみなす(安全のためチェック)
74    if ($topLevelDirToClean === '') {
75        $topLevelDirToClean = '.';
76    }
77
78    // 再帰的にディレクトリを削除する無名関数
79    // この関数はクロージャとして定義され、demonstrationStreamMkdirRecursive のスコープ内で利用されます。
80    $removeDirectoryRecursively = static function (string $dir) use (&$removeDirectoryRecursively): void {
81        if (!is_dir($dir)) {
82            return;
83        }
84        $items = array_diff(scandir($dir), ['.', '..']);
85        foreach ($items as $item) {
86            $itemPath = $dir . DIRECTORY_SEPARATOR . $item;
87            if (is_dir($itemPath)) {
88                // 無名関数自身を再帰的に呼び出す
89                $removeDirectoryRecursively($itemPath);
90            } else {
91                unlink($itemPath); // ファイルを削除
92            }
93        }
94        rmdir($dir); // 空になったディレクトリを削除
95    };
96
97    if (is_dir($topLevelDirToClean)) {
98        $removeDirectoryRecursively($topLevelDirToClean);
99        echo "ベースディレクトリ '{$topLevelDirToClean}' とその内容をクリーンアップしました。\n";
100    } else {
101        echo "クリーンアップ対象のベースディレクトリ '{$topLevelDirToClean}' が見つかりませんでした。\n";
102    }
103}
104
105// サンプルコードを実行
106// 'temp_recursive_dir' というベースディレクトリとその中に 'sub/directory' を作成します。
107demonstrationStreamMkdirRecursive('temp_recursive_dir/sub/directory');

PHPのSTREAM_MKDIR_RECURSIVEは、ストリーム操作において多階層のディレクトリを再帰的に作成する機能を示す定数です。この定数自体をコード内で直接利用することはありませんが、その機能はstream_context_createを通じて実現される'mkdir'オプションの'recursive'フラグの内部的な意味合いに対応します。

このサンプルコードは、stream_context_create関数を使って、再帰的なディレクトリ作成の動作を制御する方法を示しています。具体的には、stream_context_createのオプションとして'mkdir' => ['recursive' => true]を設定することで、指定したパスの途中に存在する親ディレクトリも自動的に作成されるようになります。

その後、設定したストリームコンテキストをmkdir関数の第4引数に渡すことで、この再帰的な作成機能が適用されます。demonstrationStreamMkdirRecursive関数は、$pathという文字列で作成したいディレクトリのパスを受け取り、ディレクトリ作成の成功を示すメッセージを表示した後、関連するファイルとディレクトリをクリーンアップします。この関数は特定の値を返さないため、戻り値はvoidです。このように、ストリームコンテキストを利用することで、PHPのファイルシステム操作関数に対して、より柔軟な振る舞いを設定できます。これは、php stream resourceという概念の一例であり、ストリーム経由でのリソース操作の基本を示しています。

PHPのSTREAM_MKDIR_RECURSIVE定数は、直接コードで指定するものではなく、stream_context_create関数で'mkdir' => ['recursive' => true]オプションを設定する際に、再帰的なディレクトリ作成機能を有効にするための内部的な意味合いを持ちます。そのため、サンプルコードのようにmkdir関数の第三引数をfalseにしても、コンテキストオプションのrecursive: trueが優先され、多階層のディレクトリが一度に作成されます。ディレクトリ作成時のパーミッション0777は開発環境向けであり、本番環境ではセキュリティのため0755など適切な最小限の値に設定することが推奨されます。また、ファイルやディレクトリ操作は予期せぬエラーで失敗する可能性があるため、必ず関数の戻り値を確認し、適切にエラーを処理するよう心がけてください。

PHP stream_context_createで再帰的ディレクトリ作成

1<?php
2
3/**
4 * 指定されたパスにディレクトリを再帰的に作成します。
5 * stream_context_create と STREAM_MKDIR_RECURSIVE を使用して、
6 * ストリームコンテキスト経由でディレクトリ作成を行います。
7 *
8 * @param string $path 作成するディレクトリのパス(例: 'my_app/data/logs')
9 * @param int $mode 作成するディレクトリのパーミッション(例: 0755)
10 * @return bool ディレクトリ作成が成功した場合は true、失敗した場合は false
11 */
12function createRecursiveDirectoryWithStreamContext(string $path, int $mode = 0755): bool
13{
14    // stream_context_create() を使用して、ストリームコンテキストを作成します。
15    // ここではデフォルトのオプションを使用していますが、必要に応じて
16    // ファイル操作の挙動をカスタマイズするオプションを追加できます。
17    $context = stream_context_create();
18
19    // stream_mkdir() 関数を使ってディレクトリを作成します。
20    // 第1引数: 作成するパス。`file://` スキームはローカルファイルシステムへの
21    //          明示的なアクセスを示します。
22    // 第2引数: パーミッション(例: 0755 は所有者に読み書き実行、グループとその他に読み書き実行を許可)
23    // 第3引数: フラグ。STREAM_MKDIR_RECURSIVE を指定することで、
24    //          途中の親ディレクトリ(例: 'my_app' や 'data')が存在しなくても自動的に作成されます。
25    // 第4引数: 作成したストリームコンテキスト。
26    $result = stream_mkdir('file://' . $path, $mode, STREAM_MKDIR_RECURSIVE, $context);
27
28    if ($result) {
29        echo "SUCCESS: ディレクトリ '{$path}' が再帰的に作成されました。\n";
30    } else {
31        echo "ERROR: ディレクトリ '{$path}' の作成に失敗しました。\n";
32    }
33
34    return $result;
35}
36
37// --- サンプル使用例 ---
38
39// 存在しない多階層のディレクトリパスを定義します。
40// 例: 'my_app' → 'data' → 'logs' → '2023' → 'q4' の順にディレクトリが作成されます。
41$targetPath = 'my_app/data/logs/2023/q4';
42
43echo "--- 最初のディレクトリ作成試行 ---\n";
44if (createRecursiveDirectoryWithStreamContext($targetPath)) {
45    // ディレクトリが実際に作成されたか確認します。
46    if (is_dir($targetPath)) {
47        echo "INFO: '{$targetPath}' が実際に存在します。\n";
48    }
49}
50
51echo "\n--- 既に存在するディレクトリの再作成試行 ---\n";
52// 既に存在するパスを再度作成しようとしても、通常はエラーになりません。
53createRecursiveDirectoryWithStreamContext($targetPath);
54
55// 作成されたディレクトリをテスト後にクリーンアップするには、
56// シェルコマンド (例: `rm -rf my_app`) を手動で実行するか、
57// 別途PHPスクリプトで削除する必要があります。
58?>

STREAM_MKDIR_RECURSIVEは、PHPのストリーム操作において、多階層のディレクトリを再帰的に作成するための定数です。この定数を指定することで、目的のパスの途中のディレクトリ(親ディレクトリ)が存在しなくても、それらを自動的に作成しながら、最終的なディレクトリまで一度に構築することができます。

サンプルコードのcreateRecursiveDirectoryWithStreamContext関数は、この定数を利用してディレクトリを作成します。まず、stream_context_create()関数を使ってストリームコンテキストを作成します。これはファイルやネットワーク操作の設定を保持するもので、この例ではデフォルトの設定で使用しています。その後、stream_mkdir()関数を呼び出し、第3引数にSTREAM_MKDIR_RECURSIVEを指定することで、再帰的なディレクトリ作成を有効にしています。

この関数の引数$pathには、作成したいディレクトリのパスを文字列で渡します。$modeは作成するディレクトリのパーミッションを整数で指定し、ファイルのアクセス権限を設定します。関数はディレクトリの作成が成功した場合はtrueを、失敗した場合はfalseを真偽値として返します。

サンプル使用例では、my_app/data/logs/2023/q4という多階層のパスを指定して関数を実行しています。これにより、my_appmy_app/datamy_app/data/logsmy_app/data/logs/2023といった全ての途中のディレクトリが、最終的なmy_app/data/logs/2023/q4ディレクトリと共に一度に作成されることを確認できます。これは、複雑なディレクトリ構造を簡単に構築したい場合に非常に有用な機能です。

このサンプルコードにおけるSTREAM_MKDIR_RECURSIVEは、指定されたパスの途中の親ディレクトリが存在しなくても自動的に作成してくれる便利な定数です。stream_mkdir関数に渡すパーミッション(例: 0755)は、作成されるディレクトリのアクセス権限を決定するため、セキュリティと利用目的を考慮した適切な値を設定することが重要です。パスの先頭にあるfile://は、ローカルファイルシステムへの操作を明示的に示しています。ユーザーからの入力をパスに利用する際は、意図しない場所へのディレクトリ作成やセキュリティリスクを防ぐため、必ず入力値の検証を行ってください。また、stream_mkdirの戻り値でディレクトリ作成の成否を必ず確認し、失敗時のエラーハンドリングを適切に実装することが大切です。stream_context_createは、今回はデフォルトですが、ストリーム操作の挙動をより細かく制御したい場合に利用します。

関連コンテンツ

関連IT用語

関連プログラミング言語