create_directory()

public function create_directory(string $directory_path, int $permissions = 0755, bool $recursive = true): bool

Description

Creates a new directory at the specified path. This method allows for the creation of nested directories if they do not exist, subject to application security restrictions.

Understanding Paths: The create_directory() method works with paths relative to your application's root directory. There is no automatic "module" or "public" folder detection - you specify exactly where you want the directory created.

Parameters

ParameterTypeDescriptionDefaultRequired
$directory_path string The path where the directory should be created. N/A Yes
$permissions int Octal notation permissions (e.g., 0755). 0755 No
$recursive bool If true, creates all parent directories in the path. If false, fails if any parent directory doesn't exist. true No

Return Value

TypeDescription
bool Returns true if the directory was created successfully or already exists.

Understanding the $recursive Parameter

The $recursive parameter controls whether the method will automatically create missing parent directories:

When $recursive is true (default):

If you try to create uploads/documents/2024 and neither uploads nor uploads/documents exist, the method will create all three directories automatically.

When $recursive is false:

If you try to create uploads/documents/2024 and uploads/documents doesn't exist, the method will fail and return false. All parent directories must already exist.

Why Use Non-Recursive Mode?

Setting $recursive to false is useful when:

  • You want to ensure a specific directory structure already exists before proceeding
  • You're validating that setup or installation steps were completed correctly
  • You want to prevent accidental directory creation in unexpected locations
  • You're implementing defensive checks in production code

How Paths Work

All paths are relative to your application's root directory (where your config, engine, and modules folders are located).

If you specify... It creates... Best for...
'uploads' /your-app/uploads/ General upload storage
'public/uploads' /your-app/public/uploads/ Web-accessible files
'modules/users/uploads' /your-app/modules/users/uploads/ Module-specific storage
'/var/www/uploads' /var/www/uploads/ Absolute path storage

Example #1

The code sample below demonstrates the most basic directory creation operation.

PHP
$this->file->create_directory('uploads/documents');

Safe to Call Multiple Times: The method returns true if the directory already exists, making it safe to call repeatedly without checking first. This "idempotent" behavior means you can call create_directory() before every upload operation without worrying about errors if the directory is already there.

Example #2

The example above shows how to create a directory with custom permissions.

PHP
// Create a private directory with restricted access
$this->file->create_directory('private/user_data', 0700);

// Create a web-accessible directory
$this->file->create_directory('public/uploads', 0755);

Understanding Permissions: The default permission 0755 gives the owner (your PHP process) full control, while others can read and access the directory. Use 0700 for sensitive data (only owner can access), or 0775 when both owner and group need write access (common in shared hosting).

Example #3

The example above demonstrates creating nested directories automatically with recursive mode.

PHP
// Creates all missing parent directories automatically
$this->file->create_directory('uploads/documents/2024/december');

// This creates:
// - uploads/
// - uploads/documents/
// - uploads/documents/2024/
// - uploads/documents/2024/december/

Example #4

The example above shows how to use non-recursive mode for validation.

PHP
public function create_user_directory(): void {
    $user_id = segment(3, 'int');
    
    // Ensure base structure exists first
    if (!$this->file->exists('uploads/users')) {
        redirect('admin/setup_required');
    }
    
    // Create user directory (fails if parent doesn't exist)
    $user_dir = 'uploads/users/' . $user_id;
    $result = $this->file->create_directory($user_dir, 0755, false);
    
    if ($result === true) {
        set_flashdata('User directory created');
        redirect('users/dashboard/' . $user_id);
    } else {
        redirect('admin/setup_required');
    }
}

When to Check First: While create_directory() is safe to call multiple times, you may want to check if a directory exists first when: (1) you need to perform different actions based on whether it's new or existing, (2) you're validating system setup, or (3) you want to provide specific user feedback. Use $this->file->exists($directory) to check before creating.

Example #5

The example above demonstrates organizing uploads into date-based directory structures.

PHP
public function upload_invoice(): void {
    // Validate file upload
    $this->validation->set_rules('userfile', 'Invoice', 'required|allowed_types[pdf]|max_size[5000]');
    
    if ($this->validation->run() === true) {
        // Create date-based directory structure
        $date_path = 'uploads/invoices/' . date('Y/m');
        $this->file->create_directory($date_path, 0755);
        
        // Configure and upload file
        $config['destination'] = $date_path;
        $file_info = $this->file->upload($config);
        
        set_flashdata('Invoice uploaded successfully');
        redirect('invoices/success');
    } else {
        $this->invoice_form();
    }
}

Example #6

The example above shows how to set up a complete application directory structure.

PHP
public function setup_application_directories(): void {
    $directories = [
        'public/uploads/images',
        'public/uploads/documents',
        'private/user_data',
        'modules/reports/exports',
        'logs/application',
        'temp/processing',
        'backups/daily'
    ];
    
    $created_count = 0;
    
    foreach ($directories as $dir) {
        $result = $this->file->create_directory($dir, 0755);
        if ($result === true) {
            $created_count++;
        }
    }
    
    set_flashdata("Setup complete: {$created_count} directories ready");
    redirect('admin/dashboard');
}

Example #7

The example above demonstrates creating user-specific directories with proper permissions.

PHP
public function initialize_user_storage(): void {
    $user_id = segment(3, 'int');
    
    // Create base user directory
    $user_base = 'modules/users/storage/' . $user_id;
    $this->file->create_directory($user_base, 0755);
    
    // Create subdirectories for different content types
    $subdirectories = ['documents', 'images', 'videos', 'temp'];
    
    foreach ($subdirectories as $subdir) {
        $full_path = $user_base . '/' . $subdir;
        $this->file->create_directory($full_path, 0755);
    }
    
    // Update user record
    $data['storage_initialized'] = true;
    $data['storage_path'] = $user_base;
    $this->model->update($user_id, $data, 'users');
    
    set_flashdata('User storage initialized');
    redirect('users/profile/' . $user_id);
}

Example #8

The example above shows validation of required directory structure during application startup.

PHP
public function validate_directory_structure(): array {
    $required_dirs = [
        'uploads' => 'Upload storage',
        'public' => 'Public assets',
        'modules' => 'Application modules',
        'logs' => 'Application logs'
    ];
    
    $missing = [];
    $validation_results = [];
    
    foreach ($required_dirs as $dir => $description) {
        // Use non-recursive mode to check if base directories exist
        $test_path = $dir . '/.test';
        $result = $this->file->create_directory($test_path, 0755, false);
        
        if ($result === false) {
            $missing[] = $description;
            $validation_results[$dir] = false;
        } else {
            // Clean up test directory
            rmdir($test_path);
            $validation_results[$dir] = true;
        }
    }
    
    return [
        'valid' => empty($missing),
        'missing' => $missing,
        'results' => $validation_results
    ];
}

Non-Recursive Validation Pattern: When using $recursive = false for validation, the method returns false instead of throwing an exception if parent directories are missing. This makes it ideal for checking system requirements without disrupting application flow.

Example #9

The example above demonstrates creating temporary processing directories with unique names.

PHP
public function start_batch_import(): void {
    $import_id = segment(3, 'int');
    
    // Create unique temporary directory for this import
    $temp_id = uniqid();
    $temp_dir = 'temp/imports/batch_' . $temp_id;
    
    $this->file->create_directory($temp_dir, 0755);
    
    // Store temp directory in session for cleanup later
    $_SESSION['import_temp_dir'] = $temp_dir;
    
    // Update import record
    $data['temp_directory'] = $temp_dir;
    $data['status'] = 'processing';
    $this->model->update($import_id, $data, 'imports');
    
    set_flashdata('Import processing started');
    redirect('imports/process/' . $import_id);
}

Example #10

The example above shows how to handle different permission requirements for different directory types.

PHP
public function setup_secure_storage(): void {
    // Public directories - web server can read
    $this->file->create_directory('public/uploads', 0755);
    $this->file->create_directory('public/assets', 0755);
    
    // Private directories - only PHP process can access
    $this->file->create_directory('private/keys', 0700);
    $this->file->create_directory('private/config', 0700);
    
    // Shared directories - PHP and group can write
    $this->file->create_directory('shared/cache', 0775);
    $this->file->create_directory('shared/sessions', 0775);
    
    // Temporary directories - PHP can write, others can read
    $this->file->create_directory('temp/uploads', 0755);
    
    set_flashdata('Storage structure created with appropriate permissions');
    redirect('admin/security');
}

Security Warning: Never use 0777 permissions on production servers. This gives everyone on the server full read/write/execute access to your directories, creating a major security risk. Stick to 0755 for general directories, 0700 for private data, and 0775 only when group write access is explicitly required.