PHPでのディレクトリ作成について

採用はこちら

PHPでディレクトリを作成する場合は、主に mkdir() 関数を使用します。

最もシンプルな書き方は次のとおりです。

mkdir('sample');

このコードを実行すると、PHPファイルを実行している場所を基準に、sample というディレクトリが作成されます。

例えば、次のような構成だったとします。

project/
├── index.php

index.php に以下のコードを書いて実行すると、

<?php
mkdir('sample');

実行後は次のような構成になります。

project/
├── index.php
└── sample/

ただし、実務では単純に mkdir() を実行するだけでは不十分な場合があります。

既に同じ名前のディレクトリが存在していたり、親ディレクトリが存在しなかったり、書き込み権限がなかったりすると、ディレクトリ作成に失敗することがあるためです。

そのため、PHPでディレクトリを作成する際は、mkdir() の使い方だけでなく、存在確認、権限、パス指定、エラーハンドリングまで理解しておくことが大切です。

目次

mkdir()関数の基本構文

mkdir() 関数の基本構文は次のとおりです。

mkdir(string $directory, int $permissions = 0777, bool $recursive = false, ?resource $context = null): bool

よく使う引数は、主に次の3つです。

mkdir(ディレクトリパス, パーミッション, 再帰的に作成するか);

例えば、次のように記述します。

mkdir('uploads/images', 0755, true);

このコードでは、uploads/images というディレクトリを作成します。

第3引数に true を指定しているため、uploads ディレクトリが存在しない場合でも、親ディレクトリを含めてまとめて作成できます。

第1引数:作成するディレクトリのパス

第1引数には、作成したいディレクトリのパスを指定します。

mkdir('uploads');

この場合、現在の実行位置を基準に uploads ディレクトリが作成されます。

ただし、相対パスは実行環境によって基準が分かりにくくなることがあります。

そのため、実務では __DIR__ を使って、現在のPHPファイルの場所を基準に指定することが多いです。

$dir = __DIR__ . '/uploads';

mkdir($dir);

__DIR__ は、現在のPHPファイルが置かれているディレクトリを表すマジック定数です。

例えば、PHPファイルが次の場所にある場合、

/var/www/html/index.php

__DIR__ は次の値になります。

/var/www/html

そのため、

$dir = __DIR__ . '/uploads';

は、次のパスを指します。

/var/www/html/uploads

相対パスよりも、__DIR__ を使った指定の方が、環境が変わっても意図しない場所にディレクトリが作成されにくくなります。

第2引数:パーミッション

第2引数には、作成するディレクトリの権限を指定します。

mkdir('uploads', 0755);

よく使われるパーミッションには、次のようなものがあります。

mkdir('uploads', 0777);
mkdir('uploads', 0755);
mkdir('uploads', 0700);

それぞれの意味は以下のとおりです。

パーミッション内容
0777すべてのユーザーが読み取り・書き込み・実行できる
0755所有者は読み取り・書き込み・実行、その他は読み取り・実行できる
0700所有者だけが読み取り・書き込み・実行できる

Webアプリケーションでは、安易に 0777 を指定するのは避けた方がよいです。

0777 は誰でも書き込みできる状態に近くなるため、サーバー構成によってはセキュリティ上のリスクが高くなります。

一般的には、まず 0755 などの必要最小限の権限を検討します。

mkdir($dir, 0755, true);

ただし、アップロードディレクトリなど、PHPからファイルを書き込む必要がある場合は、サーバーの実行ユーザーや所有者の設定によって 0755 では書き込めないこともあります。

その場合は、パーミッションだけでなく、ディレクトリの所有者、グループ、PHP-FPMやApacheの実行ユーザーなども確認する必要があります。

第3引数:親ディレクトリも作成するか

第3引数には、親ディレクトリを含めて再帰的に作成するかどうかを指定します。

デフォルトは false です。

例えば、次のようなディレクトリを作りたいとします。

uploads/2026/06

しかし、uploads2026 が存在しない状態で次のコードを実行すると、ディレクトリ作成に失敗する可能性があります。

mkdir('uploads/2026/06');

このような場合は、第3引数に true を指定します。

mkdir('uploads/2026/06', 0755, true);

これにより、存在しない親ディレクトリも含めて作成できます。

uploads/
└── 2026/
    └── 06/

画像アップロードやログ保存、キャッシュ保存などでは、日付ごとに階層を分けることが多いため、第3引数の true は実務でもよく使います。

ディレクトリが存在しない場合だけ作成する

既に同じディレクトリが存在している状態で mkdir() を実行すると、警告が出たり、false が返ったりすることがあります。

そのため、実務ではディレクトリの存在を確認してから作成するのが基本です。

<?php

$dir = __DIR__ . '/uploads';

if (!is_dir($dir)) {
    mkdir($dir, 0755, true);
}

このコードでは、uploads ディレクトリが存在しない場合だけ mkdir() を実行しています。

file_exists()よりis_dir()を使う

ディレクトリの存在確認では、file_exists() よりも is_dir() を使うのがおすすめです。

例えば、次のように書くこともできます。

if (!file_exists($dir)) {
    mkdir($dir);
}

しかし、file_exists() は、ファイルでもディレクトリでも存在すれば true を返します。

つまり、uploads という名前のファイルが存在している場合でも、file_exists('uploads')true になります。

一方で、is_dir() は対象がディレクトリである場合だけ true を返します。

if (!is_dir($dir)) {
    mkdir($dir, 0755, true);
}

ディレクトリを作成する処理では、「そのパスが存在するか」だけでなく、「それがディレクトリかどうか」が重要です。

そのため、基本的には is_dir() を使った方が安全です。

同名のファイルが存在する場合も考慮する

より厳密に処理するなら、同名のファイルが存在するケースも考慮します。

<?php

$dir = __DIR__ . '/uploads';

if (file_exists($dir) && !is_dir($dir)) {
    throw new RuntimeException('同名のファイルが存在します。');
}

if (!is_dir($dir)) {
    if (!mkdir($dir, 0755, true) && !is_dir($dir)) {
        throw new RuntimeException('ディレクトリを作成できませんでした。');
    }
}

このコードでは、まず同じパスにファイルが存在していないかを確認しています。

もし uploads という名前のファイルが存在している場合、同じ名前のディレクトリは作成できません。

そのため、例外を投げて処理を中断しています。

mkdir()の戻り値を確認する

mkdir() は、ディレクトリ作成に成功すると true、失敗すると false を返します。

<?php

$dir = __DIR__ . '/uploads';

$result = mkdir($dir, 0755, true);

if ($result) {
    echo 'ディレクトリを作成しました。';
} else {
    echo 'ディレクトリの作成に失敗しました。';
}

ただし、この書き方だけでは実務上やや不十分です。

既にディレクトリが存在している場合、mkdir() は失敗扱いになることがあります。

しかし、最終的にディレクトリが存在していれば、処理としては問題ないケースもあります。

そのため、次のように mkdir() の結果と is_dir() の結果を組み合わせると、より安全です。

<?php

$dir = __DIR__ . '/uploads';

if (!is_dir($dir)) {
    if (!mkdir($dir, 0755, true) && !is_dir($dir)) {
        throw new RuntimeException('ディレクトリを作成できませんでした。');
    }
}

この書き方は、複数のリクエストが同時に同じディレクトリを作成しようとした場合にも有効です。

例えば、2つの処理がほぼ同時に uploads ディレクトリを作成しようとすると、片方が先に成功し、もう片方の mkdir() は失敗することがあります。

しかし、その時点でディレクトリ自体が存在していれば、実質的には問題ありません。

そのため、

!mkdir($dir, 0755, true) && !is_dir($dir)

という条件にすることで、mkdir() が失敗しても、最終的にディレクトリが存在していればエラーにしないようにできます。

パーミッションとumaskの注意点

mkdir() の第2引数でパーミッションを指定しても、必ずその通りの権限で作成されるとは限りません。

例えば、次のように書いたとします。

mkdir('uploads', 0777);

しかし、実際に作成されたディレクトリの権限が 07550750 になることがあります。

これは、サーバー側の umask が影響しているためです。

umaskとは

umask とは、ファイルやディレクトリを作成するときに、許可しない権限を差し引く仕組みです。

例えば、0777 を指定しても、サーバーの umask0022 の場合、実際には 0755 のような権限で作成されることがあります。

つまり、PHPで指定したパーミッションは、サーバーの設定によって調整されることがあります。

mkdir($dir, 0777, true);

このように書いても、必ず 0777 になるとは限りません。

chmod()で権限を変更できる

作成後に権限を変更したい場合は、chmod() を使います。

<?php

$dir = __DIR__ . '/uploads';

if (!is_dir($dir)) {
    mkdir($dir, 0755, true);
    chmod($dir, 0755);
}

ただし、chmod() は必ず使うべきものではありません。

サーバー環境によっては chmod() が制限されていたり、期待通りに反映されなかったりすることもあります。

また、mkdir() で複数階層を再帰的に作成した場合、直後の chmod($dir, 0755) が適用されるのは、基本的には最後のディレクトリです。

例えば、次のようなコードがあったとします。

$dir = __DIR__ . '/uploads/2026/06';

mkdir($dir, 0755, true);
chmod($dir, 0755);

この場合、chmod() の対象になるのは主に次のディレクトリです。

uploads/2026/06

途中で作成された uploadsuploads/2026 にも同じ権限が必ず適用されるわけではありません。

そのため、権限を厳密に管理したい場合は、サーバー側の所有者やグループ設定も含めて設計する必要があります。

Windowsではpermissionsが無視される

LinuxやmacOSなどのUnix系環境では、07550777 のようなパーミッション指定が意味を持ちます。

一方で、Windows環境では、mkdir()permissions 引数は基本的に無視されます。

そのため、Windows環境でPHPを動かしている場合は、

mkdir($dir, 0755, true);

と書いても、0755 の権限がそのまま反映されるわけではありません。

XAMPPなどのローカル開発環境では特に、Linuxサーバーとは権限の扱いが異なる点に注意しましょう。

実務向けのディレクトリ作成関数

ディレクトリ作成処理は、アップロード機能、CSV出力、キャッシュ保存、ログ保存など、さまざまな場面で使います。

毎回同じ処理を書くのは手間なので、関数化しておくと便利です。

<?php

function ensureDirectoryExists(string $dir, int $permission = 0755): void
{
    if (file_exists($dir) && !is_dir($dir)) {
        throw new RuntimeException("同名のファイルが既に存在します: {$dir}");
    }

    if (!is_dir($dir)) {
        if (!mkdir($dir, $permission, true) && !is_dir($dir)) {
            throw new RuntimeException("ディレクトリを作成できませんでした: {$dir}");
        }
    }
}

この関数では、次の処理を行っています。

1. 同名のファイルが存在していないか確認する
2. ディレクトリが存在しない場合だけ作成する
3. 親ディレクトリも含めて作成する
4. 作成に失敗した場合は例外を投げる
5. 同時アクセスによる作成済み状態も考慮する

使い方は次のとおりです。

<?php

$dir = __DIR__ . '/uploads/images';

ensureDirectoryExists($dir);

このようにしておけば、必要なディレクトリが存在しない場合に自動で作成できます。

書き込み権限も確認する関数

画像アップロードやCSV出力など、ファイルを書き込む用途で使う場合は、ディレクトリ作成後に is_writable() で書き込み権限を確認するとより安全です。

<?php

function ensureWritableDirectory(string $dir, int $permission = 0755): void
{
    if (file_exists($dir) && !is_dir($dir)) {
        throw new RuntimeException("同名のファイルが既に存在します: {$dir}");
    }

    if (!is_dir($dir)) {
        if (!mkdir($dir, $permission, true) && !is_dir($dir)) {
            throw new RuntimeException("ディレクトリを作成できませんでした: {$dir}");
        }
    }

    if (!is_writable($dir)) {
        throw new RuntimeException("ディレクトリに書き込み権限がありません: {$dir}");
    }
}

使い方は次のとおりです。

<?php

try {
    $dir = __DIR__ . '/uploads/' . date('Y/m');

    ensureWritableDirectory($dir);

    echo 'ディレクトリを利用できます。';
} catch (RuntimeException $e) {
    error_log($e->getMessage());
    echo 'ディレクトリの準備に失敗しました。';
}

本番環境では、エラーメッセージをそのまま画面に表示するのではなく、error_log() などでログに記録し、ユーザーには汎用的なメッセージを表示する方が安全です。

ファイルアップロード用ディレクトリを作成する例

画像アップロード機能では、年月ごとにディレクトリを分けて保存することがあります。

例えば、次のような構成です。

uploads/
└── 2026/
    └── 06/
        └── image.jpg

このようなディレクトリをPHPで作成する場合は、次のように書けます。

<?php

function ensureWritableDirectory(string $dir, int $permission = 0755): void
{
    if (file_exists($dir) && !is_dir($dir)) {
        throw new RuntimeException("同名のファイルが既に存在します: {$dir}");
    }

    if (!is_dir($dir)) {
        if (!mkdir($dir, $permission, true) && !is_dir($dir)) {
            throw new RuntimeException("ディレクトリを作成できませんでした: {$dir}");
        }
    }

    if (!is_writable($dir)) {
        throw new RuntimeException("ディレクトリに書き込み権限がありません: {$dir}");
    }
}

try {
    $baseDir = __DIR__ . '/uploads';
    $uploadDir = $baseDir . '/' . date('Y/m');

    ensureWritableDirectory($uploadDir);

    echo '保存先ディレクトリ: ' . $uploadDir;
} catch (RuntimeException $e) {
    error_log($e->getMessage());
    echo 'アップロード先の準備に失敗しました。';
}

このコードでは、現在の年月を使って保存先ディレクトリを作成しています。

例えば、2026年6月に実行した場合、次のようなディレクトリが作成されます。

uploads/2026/06

アップロード処理と組み合わせる場合

実際にファイルアップロード処理と組み合わせる場合は、ディレクトリ作成後に move_uploaded_file() などでファイルを保存します。

<?php

$uploadDir = __DIR__ . '/uploads/' . date('Y/m');

ensureWritableDirectory($uploadDir);

$filename = 'sample.jpg';
$savePath = $uploadDir . '/' . $filename;

// 例:アップロードされたファイルを保存する場合
// move_uploaded_file($_FILES['image']['tmp_name'], $savePath);

ただし、アップロード機能では、ディレクトリ作成だけでなく、ファイル名や拡張子、MIMEタイプの検証も重要です。

ユーザーがアップロードしたファイル名をそのまま保存すると、上書きやパストラバーサル、スクリプト実行などのリスクが生じる可能性があります。

そのため、アップロードファイルはランダムなファイル名に変更し、許可する拡張子やMIMEタイプを制限するのが基本です。

パス指定の注意点

PHPでディレクトリを作成するときは、パスの指定方法にも注意が必要です。

特に、相対パスを使う場合は、思っている場所とは違う場所を基準にしてしまうことがあります。

相対パスで指定する場合

相対パスで指定する場合は、次のように書きます。

mkdir('uploads');

このコードは、現在の実行位置を基準に uploads ディレクトリを作成します。

ただし、PHPファイルが別ファイルから読み込まれている場合や、CLIで実行する場合などは、想定と異なる場所が基準になることがあります。

そのため、実務では相対パスだけに頼らない方が安全です。

__DIR__を使って指定する場合

__DIR__ を使うと、現在のPHPファイルが置かれているディレクトリを基準にできます。

$dir = __DIR__ . '/uploads';

mkdir($dir, 0755, true);

この書き方であれば、実行位置に左右されにくく、どこにディレクトリを作るのかが明確になります。

DIRECTORY_SEPARATORについて

PHPでは、OSごとのディレクトリ区切り文字を表す DIRECTORY_SEPARATOR という定数があります。

$dir = __DIR__ . DIRECTORY_SEPARATOR . 'uploads';

Windowsでは \、LinuxやmacOSでは / が区切り文字として使われます。

ただし、PHPではWindows環境でも / が使えることが多いため、Webアプリケーションでは次のような書き方でも問題ないケースが多いです。

$dir = __DIR__ . '/uploads';

可読性を重視して / を使うか、OS差異を意識して DIRECTORY_SEPARATOR を使うかは、プロジェクトの方針に合わせるとよいでしょう。

ユーザー入力をディレクトリ名に使う場合の注意点

ユーザー入力をディレクトリ名に使う場合は、特に注意が必要です。

例えば、ユーザー名ごとにディレクトリを作成するために、次のようなコードを書いたとします。

<?php

$username = $_POST['username'];

$dir = __DIR__ . '/uploads/' . $username;

mkdir($dir, 0755, true);

このコードは危険です。

なぜなら、ユーザーが意図しない文字列を送信できるためです。

例えば、次のような値が送られてきた場合、

../../danger

想定していない場所にディレクトリを作成しようとする可能性があります。

このような攻撃は、パストラバーサルと呼ばれます。

ホワイトリスト方式で許可する文字を制限する

ユーザー入力をディレクトリ名に使う場合は、使ってよい文字だけを明確に制限します。

<?php

$name = $_POST['name'] ?? '';

if (!preg_match('/\A[a-zA-Z0-9_-]+\z/', $name)) {
    throw new RuntimeException('不正なディレクトリ名です。');
}

$dir = __DIR__ . '/uploads/' . $name;

ensureWritableDirectory($dir);

この例では、英数字、アンダースコア、ハイフンだけを許可しています。

/\A[a-zA-Z0-9_-]+\z/

危険な文字を後から削る方法よりも、「許可した文字だけを通す」ホワイトリスト方式の方が安全です。

ユーザー名よりIDやUUIDを使う

ユーザーごとのディレクトリを作成する場合は、ユーザー名をそのまま使うよりも、データベース上のIDやUUIDなど、アプリケーション側で管理している安全な値を使う方がおすすめです。

例えば、次のような形です。

$userId = 123;

$dir = __DIR__ . '/uploads/users/' . $userId;

ensureWritableDirectory($dir);

ユーザー名は変更される可能性があり、記号や日本語を含むこともあります。

一方で、IDやUUIDであれば、ディレクトリ名として扱いやすく、管理もしやすくなります。

realpath()を使う場合の注意点

パスの安全性を確認するために realpath() を使うことがあります。

$path = realpath($dir);

ただし、realpath() は存在しないパスに対しては false を返します。

つまり、これから作成するディレクトリに対して、作成前に realpath() を使うことはできません。

$dir = __DIR__ . '/uploads/new-directory';

var_dump(realpath($dir)); // 存在しない場合は false

作成前にパスを検証したい場合は、既に存在している親ディレクトリに対して realpath() を使うとよいです。

<?php

$baseDir = realpath(__DIR__ . '/uploads');

if ($baseDir === false) {
    throw new RuntimeException('基準ディレクトリが存在しません。');
}

$name = $_GET['name'] ?? '';

if (!preg_match('/\A[a-zA-Z0-9_-]+\z/', $name)) {
    throw new RuntimeException('不正なディレクトリ名です。');
}

$dir = $baseDir . DIRECTORY_SEPARATOR . $name;

ensureWritableDirectory($dir);

このコードでは、まず基準となる uploads ディレクトリが存在しているかを確認しています。

そのうえで、ユーザー入力を検証し、安全なディレクトリ名だけを使ってパスを組み立てています。

ディレクトリ作成に失敗する主な原因

PHPでディレクトリ作成に失敗する場合、よくある原因はいくつかあります。

エラーメッセージだけでは分かりにくいこともあるため、原因ごとに確認しましょう。

親ディレクトリが存在しない

次のように、深い階層のディレクトリを作ろうとした場合、

mkdir('uploads/images/icons');

親ディレクトリである uploadsimages が存在しないと、作成に失敗することがあります。

この場合は、第3引数に true を指定します。

mkdir('uploads/images/icons', 0755, true);

書き込み権限がない

PHPを実行しているユーザーに書き込み権限がない場合、ディレクトリ作成は失敗します。

例えば、ApacheやNginx、PHP-FPMの実行ユーザーが、対象の親ディレクトリに書き込めない場合です。

この場合は、PHPコードだけでは解決できないこともあります。

確認すべき項目は次のとおりです。

- 親ディレクトリのパーミッション
- ディレクトリの所有者
- グループ設定
- PHP-FPMやApacheの実行ユーザー
- open_basedirの制限
- SELinuxやAppArmorの制限
- レンタルサーバーの仕様

同名のファイルが存在する

作成したいディレクトリと同じ名前のファイルが既に存在する場合、ディレクトリは作成できません。

例えば、uploads というファイルが既に存在している状態で、uploads ディレクトリを作ろうとしても失敗します。

この場合は、次のように事前に確認します。

if (file_exists($dir) && !is_dir($dir)) {
    throw new RuntimeException('同名のファイルが存在します。');
}

パスが間違っている

相対パスを使っている場合、思っている場所と違う場所にディレクトリを作ろうとしていることがあります。

このようなトラブルを避けるには、__DIR__ を使ってパスを明確にするのがおすすめです。

$dir = __DIR__ . '/uploads';

open_basedirの制限がある

サーバー設定で open_basedir が有効になっている場合、PHPがアクセスできるディレクトリが制限されます。

その範囲外にディレクトリを作成しようとすると、失敗することがあります。

特にレンタルサーバーやセキュリティ設定が厳しい環境では、open_basedir の影響を受けることがあります。

よくあるエラーと対処法

PHPでディレクトリを作成する際には、いくつかのエラーが発生することがあります。

代表的なエラーと対処法を見ていきましょう。

Warning: mkdir(): File exists

このエラーは、作成しようとしているディレクトリが既に存在している場合に発生することがあります。

対処法は、mkdir() を実行する前に is_dir() で確認することです。

if (!is_dir($dir)) {
    mkdir($dir, 0755, true);
}

同名のファイルが存在するケースも考慮するなら、次のようにします。

if (file_exists($dir) && !is_dir($dir)) {
    throw new RuntimeException('同名のファイルが存在します。');
}

Warning: mkdir(): Permission denied

このエラーは、PHPに書き込み権限がない場合に発生します。

対象ディレクトリや親ディレクトリのパーミッション、所有者、グループ、PHPの実行ユーザーを確認しましょう。

コード側では、作成後に is_writable() を使って書き込み可能か確認できます。

if (!is_writable($dir)) {
    throw new RuntimeException('ディレクトリに書き込み権限がありません。');
}

Warning: mkdir(): No such file or directory

このエラーは、親ディレクトリが存在しない場合に発生することがあります。

対処法は、第3引数に true を指定することです。

mkdir($dir, 0755, true);

Warning: mkdir(): Not a directory

このエラーは、パスの途中にディレクトリではなくファイルが存在している場合に発生することがあります。

例えば、uploads というファイルが存在している状態で、次のように実行すると失敗します。

mkdir('uploads/images', 0755, true);

この場合、uploads がディレクトリではなくファイルなので、その下に images を作成できません。

Web公開ディレクトリに作成する場合の注意点

画像アップロードなどでは、Web公開ディレクトリ内に uploads ディレクトリを作ることがあります。

例えば、次のような構成です。

public/
└── uploads/

この場合、アップロードされたファイルにブラウザから直接アクセスできる可能性があります。

画像ファイルだけであれば問題ないケースもありますが、PHPファイルやHTMLファイルなどをアップロードされると危険です。

アップロードディレクトリではPHPを実行させない

アップロードディレクトリでは、PHPファイルを実行できないようにすることが重要です。

Apache環境では、.htaccess で制限できる場合があります。

<FilesMatch "\.php$">
    Require all denied
</FilesMatch>

また、Apache + mod_php の環境では、次のような設定が使える場合もあります。

php_flag engine off

ただし、これらの設定はサーバー構成に依存します。

PHP-FPM環境、Nginx環境、レンタルサーバーなどでは、.htaccess が使えなかったり、設定が反映されなかったりすることがあります。

そのため、アップロードディレクトリでPHPを実行させない設定は、サーバー環境に合わせて行う必要があります。

Web公開領域の外に保存する方法もある

より安全に設計するなら、アップロードファイルをWeb公開領域の外に保存する方法もあります。

例えば、次のような構成です。

project/
├── public/
│   └── index.php
└── storage/
    └── uploads/

この場合、public がWeb公開ディレクトリで、storage は直接ブラウザからアクセスできない場所です。

public/index.php から storage/uploads に保存する場合は、次のように指定できます。

$dir = dirname(__DIR__) . '/storage/uploads';

ensureWritableDirectory($dir);

この設計にすると、アップロードされたファイルへ直接URLでアクセスされにくくなります。

画像を表示したい場合は、PHP側で認証や権限確認を行ったうえで、必要なファイルだけを返す設計にできます。

WordPressでディレクトリを作成する場合

WordPressでアップロードディレクトリを扱う場合は、PHP標準の mkdir() を直接使うより、WordPressの関数を使う方が適しています。

代表的なのが wp_upload_dir()wp_mkdir_p() です。

<?php

$upload_dir = wp_upload_dir();

$path = $upload_dir['basedir'] . '/custom-folder';

if (!is_dir($path)) {
    wp_mkdir_p($path);
}

wp_upload_dir() は、WordPressのアップロードディレクトリ情報を取得する関数です。

basedir には、アップロードディレクトリのサーバー上のパスが入ります。

一方、wp_mkdir_p() は、親ディレクトリを含めて再帰的にディレクトリを作成するためのWordPress関数です。

WordPressプラグインやテーマ内でディレクトリを作成する場合は、できるだけWordPressの関数を使う方が、WordPressの仕様に沿った実装になります。

Laravelでディレクトリを作成する場合

Laravelでは、PHP標準の mkdir() を使うこともできますが、Laravelの仕組みに合わせるなら StorageFile ファサードを使うことが多いです。

Storageを使う場合

Laravelでストレージ上にディレクトリを作る場合は、次のように書けます。

use Illuminate\Support\Facades\Storage;

Storage::makeDirectory('uploads');

このコードは、デフォルトのdisk上に uploads ディレクトリを作成します。

保存先は、Laravelの config/filesystems.php の設定に依存します。

そのため、必ず storage/app/uploads に作成されると断定するのではなく、「デフォルトdiskの設定に従って作成される」と理解しておく必要があります。

public diskを使う場合は、次のように書きます。

Storage::disk('public')->makeDirectory('uploads');

多くのLaravel環境では、public diskは storage/app/public に対応していますが、これも設定によって変わる可能性があります。

Fileファサードを使う場合

物理パスを直接指定してディレクトリを作成したい場合は、File ファサードも使えます。

use Illuminate\Support\Facades\File;

File::ensureDirectoryExists(storage_path('app/uploads'), 0755, true);

または、次のように書くこともできます。

File::makeDirectory(storage_path('app/uploads'), 0755, true, true);

Laravelでは、保存先を抽象化したい場合は Storage、実際のファイルシステム上のパスを扱いたい場合は File を使うと整理しやすいです。

PHPでディレクトリを作成する際のおすすめ実装

通常のPHPアプリケーションで、汎用的に使うなら次のような関数を用意しておくと便利です。

<?php

function ensureWritableDirectory(string $dir, int $permission = 0755): void
{
    if (file_exists($dir) && !is_dir($dir)) {
        throw new RuntimeException("同名のファイルが既に存在します: {$dir}");
    }

    if (!is_dir($dir)) {
        if (!mkdir($dir, $permission, true) && !is_dir($dir)) {
            throw new RuntimeException("ディレクトリを作成できませんでした: {$dir}");
        }
    }

    if (!is_writable($dir)) {
        throw new RuntimeException("ディレクトリに書き込み権限がありません: {$dir}");
    }
}

この関数は、次の点を考慮しています。

- 既にディレクトリがある場合は何もしない
- 同名のファイルがある場合はエラーにする
- 親ディレクトリも含めて作成する
- 同時アクセスによる作成済み状態を考慮する
- 作成後に書き込み権限を確認する

画像アップロード、CSV出力、ログ保存、キャッシュ生成など、ファイルを書き込む処理では、このような関数を用意しておくと実装が安定します。

使い方は次のとおりです。

<?php

try {
    $dir = __DIR__ . '/uploads/' . date('Y/m');

    ensureWritableDirectory($dir);

    echo 'ディレクトリの準備が完了しました。';
} catch (RuntimeException $e) {
    error_log($e->getMessage());
    echo 'ディレクトリの準備に失敗しました。';
}

本番環境では、詳細なエラーメッセージを画面に出すのではなく、ログに記録して、ユーザーには一般的なエラーメッセージを表示するのが安全です。

PHPでディレクトリを作成する際のまとめ

PHPでディレクトリを作成する基本は、mkdir() 関数を使うことです。

最もシンプルには、次のように書けます。

mkdir('uploads');

しかし、実務ではこれだけでは不十分です。

ディレクトリが既に存在している場合、親ディレクトリが存在しない場合、同名のファイルがある場合、書き込み権限がない場合など、さまざまなケースを考慮する必要があります。

実務では、次のような書き方が基本になります。

<?php

$dir = __DIR__ . '/uploads';

if (!is_dir($dir)) {
    if (!mkdir($dir, 0755, true) && !is_dir($dir)) {
        throw new RuntimeException('ディレクトリを作成できませんでした。');
    }
}

さらに、ファイルを書き込む用途であれば、is_writable() による確認も入れると安全です。

if (!is_writable($dir)) {
    throw new RuntimeException('ディレクトリに書き込み権限がありません。');
}

PHPでディレクトリを作成する際に重要なのは、次のポイントです。

- mkdir()でディレクトリを作成する
- 存在確認にはis_dir()を使う
- 親ディレクトリも作る場合は第3引数にtrueを指定する
- パス指定には__DIR__を使うと安全
- 0777は安易に使わない
- permissionsはumaskの影響を受ける
- Windowsではpermissionsが基本的に無視される
- ユーザー入力をそのままパスに使わない
- アップロード用途ではis_writable()も確認する
- 本番環境では詳細なエラーを画面に表示しない

ディレクトリ作成は一見シンプルな処理ですが、アップロード機能やログ保存など、Webアプリケーションの重要な処理と関わることが多い部分です。

そのため、mkdir() の基本だけでなく、権限、パス、セキュリティ、エラーハンドリングまで意識して実装することが大切です。

以上、PHPでのディレクトリ作成についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次