Navigation

Php

How to Create Directories Recursively with mkdir()

Create nested directory structures in one command using PHP's mkdir() with recursive flag - no need for manual parent directory checking.

Table Of Contents

Here's the Solution

<?php

// Basic recursive directory creation
if (!mkdir('/path/to/deep/nested/directories', 0755, true)) {
    throw new RuntimeException('Failed to create directories');
}

// Safe directory creation with error handling
function createDirectorySafely(string $path, int $permissions = 0755): bool {
    if (is_dir($path)) {
        return true; // Already exists
    }
    
    if (!mkdir($path, $permissions, true)) {
        $error = error_get_last();
        throw new RuntimeException("Cannot create directory '$path': " . $error['message']);
    }
    
    return true;
}

// Create upload directories by date
function createUploadDirectory(string $baseDir = 'uploads'): string {
    $datePath = date('Y/m/d');
    $fullPath = $baseDir . '/' . $datePath;
    
    createDirectorySafely($fullPath);
    
    return $fullPath;
}

// Organize files by category
function createCategoryDirectories(string $baseDir, array $categories): array {
    $createdPaths = [];
    
    foreach ($categories as $category) {
        $categoryPath = $baseDir . '/' . strtolower($category);
        createDirectorySafely($categoryPath);
        $createdPaths[$category] = $categoryPath;
    }
    
    return $createdPaths;
}

// Create user-specific directories
function createUserDirectory(int $userId, string $baseDir = 'users'): string {
    // Create nested structure: users/1/2/3/123
    $userIdStr = (string)$userId;
    $pathParts = [$baseDir];
    
    // Split user ID into directory levels for better file system performance
    for ($i = 0; $i < strlen($userIdStr); $i++) {
        $pathParts[] = $userIdStr[$i];
    }
    $pathParts[] = $userIdStr;
    
    $userPath = implode('/', $pathParts);
    createDirectorySafely($userPath);
    
    return $userPath;
}

// Create cache directory structure
function setupCacheDirectories(string $cacheRoot = 'cache'): array {
    $cacheStructure = [
        'cache/views',
        'cache/data',
        'cache/sessions',
        'cache/temp',
        'cache/compiled'
    ];
    
    $createdDirs = [];
    
    foreach ($cacheStructure as $dir) {
        createDirectorySafely($dir);
        $createdDirs[] = $dir;
    }
    
    return $createdDirs;
}

// Application directory setup
function initializeAppDirectories(string $appRoot): void {
    $requiredDirs = [
        'storage/logs',
        'storage/cache',
        'storage/sessions',
        'storage/uploads/images',
        'storage/uploads/documents',
        'storage/uploads/temp',
        'public/assets/css',
        'public/assets/js',
        'public/assets/images',
        'config',
        'tmp'
    ];
    
    foreach ($requiredDirs as $dir) {
        $fullPath = $appRoot . '/' . $dir;
        createDirectorySafely($fullPath);
        
        // Create .gitkeep for empty directories
        $gitkeepFile = $fullPath . '/.gitkeep';
        if (!file_exists($gitkeepFile)) {
            touch($gitkeepFile);
        }
    }
}

// Create backup directory with timestamp
function createBackupDirectory(string $backupRoot = 'backups'): string {
    $timestamp = date('Y-m-d_H-i-s');
    $backupPath = $backupRoot . '/' . date('Y/m') . '/' . $timestamp;
    
    createDirectorySafely($backupPath);
    
    return $backupPath;
}

// Permission-aware directory creation
function createDirectoryWithPermissions(string $path, string $owner = null, string $group = null): bool {
    createDirectorySafely($path, 0755);
    
    // Set ownership if running as appropriate user
    if ($owner && function_exists('chown')) {
        chown($path, $owner);
    }
    
    if ($group && function_exists('chgrp')) {
        chgrp($path, $group);
    }
    
    return true;
}

// Usage examples
try {
    // Create upload directory for today
    $uploadDir = createUploadDirectory();
    echo "Upload directory created: $uploadDir\n";
    
    // Create category directories
    $categories = ['Images', 'Documents', 'Videos', 'Audio'];
    $categoryPaths = createCategoryDirectories('media', $categories);
    print_r($categoryPaths);
    
    // Create user directory
    $userDir = createUserDirectory(12345);
    echo "User directory: $userDir\n";
    
    // Setup cache directories
    $cacheDirs = setupCacheDirectories();
    echo "Cache directories created: " . count($cacheDirs) . " directories\n";
    
    // Initialize application directories
    initializeAppDirectories('/var/www/myapp');
    echo "Application directories initialized\n";
    
    // Create backup directory
    $backupDir = createBackupDirectory();
    echo "Backup directory: $backupDir\n";
    
} catch (RuntimeException $e) {
    echo "Error: " . $e->getMessage() . "\n";
}

// Verify directory creation
function verifyDirectoryStructure(array $expectedDirs): array {
    $status = [];
    
    foreach ($expectedDirs as $dir) {
        $status[$dir] = [
            'exists' => is_dir($dir),
            'writable' => is_writable($dir),
            'readable' => is_readable($dir)
        ];
    }
    
    return $status;
}

// Check created directories
$expectedDirs = ['uploads/2024/01/15', 'cache/views', 'storage/logs'];
$dirStatus = verifyDirectoryStructure($expectedDirs);
print_r($dirStatus);

Why This Approach Rocks

mkdir() with the recursive flag offers powerful directory creation:

  1. One Command: Creates entire nested structure in single call
  2. Parent Creation: Automatically creates missing parent directories
  3. Permission Control: Set permissions for all created directories
  4. Error Handling: Returns false on failure for proper error checking

Key Parameters:

  • $pathname - Directory path to create
  • $mode - Permissions (0755 is common default)
  • $recursive - Set to true to create parent directories

Best Practices:

  • Always check if directory exists first
  • Use appropriate permissions (0755 for most cases)
  • Handle errors appropriately
  • Consider using absolute paths for clarity

Perfect for application setup, file organization, and dynamic directory structures.

Share this article

Add Comment

No comments yet. Be the first to comment!

More from Php