PHP Classes

File: docs/CONFIGURATION_FALLBACKS.md

Recommend this page to a friend!
  Packages of Adrian M   upMVC   docs/CONFIGURATION_FALLBACKS.md   Download  
File: docs/CONFIGURATION_FALLBACKS.md
Role: Auxiliary data
Content type: text/markdown
Description: Auxiliary data
Class: upMVC
Pure PHP web development without other frameworks
Author: By
Last change: Update of docs/CONFIGURATION_FALLBACKS.md
Date: 2 months ago
Size: 18,635 bytes
 

Contents

Class file image Download

? Configuration Fallbacks System

Overview

upMVC uses a five-level fallback system that allows the system to work even without complete configuration. This enables quick testing, gradual configuration, and flexible deployment strategies.

Core Philosophy: Start simple, configure as you grow.

? Why Fallbacks?

Benefits

? Quick Start - System works immediately without full configuration ? Gradual Configuration - Add settings only when you need them ? Flexible Deployment - Different configs for dev/staging/production ? No Breaking Errors - Missing config? Fallback handles it ? Development Friendly - Code defaults for rapid development

Use Cases

  • ? Quick testing without .env setup
  • ? Static sites or API-only projects (no database needed)
  • ? Local development with default settings
  • ? Production with secure .env configuration

? Fallback Priority Summary

| Setting | Priority 1 (Highest) | Priority 2 (Fallback) | File Location | |---------|---------------------|----------------------|---------------| | Paths & Domain | .env SITE_PATH, DOMAIN_NAME | Config.php $fallbacks | /etc/Config.php | | Protected Routes | .env PROTECTED_ROUTES | start.php $defaultProtectedRoutes | /etc/start.php | | Database Credentials | .env DB_* variables | ConfigDatabase.php | /etc/ConfigDatabase.php | | Session Configuration | Config::get('session') | Hardcoded defaults | /etc/Config.php line 215 | | Security/Middleware | .env via ConfigManager | Hardcoded defaults | /etc/Start.php line 158+ |

1?? Path & Domain Fallbacks

Location: /etc/Config.php

Configuration Array

/
 * Fallback configuration values for path and domain
 * 
 * Used only if .env file is missing or values are not set.
 * In normal operation, .env values are always used.
 */
private static $fallbacks = [
    'site_path' => '/upMVC',              // Installation folder or '' for root
    'domain_name' => 'http://localhost',  // Domain URL without trailing slash
];

Priority Logic

1. Check .env for SITE_PATH and DOMAIN_NAME
   ? If found: Use .env values ?
   ? If missing: Continue to fallback
   
2. Use Config.php $fallbacks array
   ? Returns default values

How It Works

// In Config.php
public static function getSitePath(): string
{
    // Priority 1: .env file
    // Priority 2: $fallbacks array
    return Environment::get('SITE_PATH', self::$fallbacks['site_path']);
}

public static function getDomainName(): string
{
    return Environment::get('DOMAIN_NAME', self::$fallbacks['domain_name']);
}

Used For

  • ? `BASE_URL` constant construction
  • ? Routing and URL processing
  • ? Asset paths (CSS, JS, images)
  • ? Redirect URLs
  • ? Link generation in views

Configuration Examples

Production (.env):

SITE_PATH=
DOMAIN_NAME=https://mysite.com

Development (.env):

SITE_PATH=/upMVC
DOMAIN_NAME=http://localhost

Quick Testing (no .env):

Uses Config.php fallbacks automatically
No configuration needed!

When to Edit

Edit .env: Production, staging, or when deploying Edit Config.php fallbacks: Default development values for your team

2?? Protected Routes Fallbacks

Location: /etc/start.php

Configuration Array

/
 * Default protected routes requiring authentication
 * 
 * These routes require user authentication before access.
 * Can be overridden via PROTECTED_ROUTES in .env (comma-separated list)
 */
private static $defaultProtectedRoutes = [
    '/dashboardexample/*',  // Dashboard example module
    '/admin/*',             // Admin panel (all routes)
    '/users/*',             // User management (all routes)
    '/moda'                 // Modal example route
];

Priority Logic

1. Check .env for PROTECTED_ROUTES
   ? If found: Parse comma-separated list ?
   ? If missing: Continue to fallback
   
2. Use start.php $defaultProtectedRoutes array
   ? Returns default protected routes

How It Works

// In start.php
private function getProtectedRoutes(): array
{
    // Priority 1: .env file (comma-separated)
    $envRoutes = Environment::get('PROTECTED_ROUTES', '');
    
    if (!empty($envRoutes)) {
        return array_map('trim', explode(',', $envRoutes));
    }
    
    // Priority 2: $defaultProtectedRoutes array
    return self::$defaultProtectedRoutes;
}

Used For

  • ? `AuthMiddleware` route protection
  • ? Session-based authentication checks
  • ? Redirect to login for unauthorized access
  • ? Wildcard pattern matching (`/admin/*`)

Configuration Examples

Production (.env):

PROTECTED_ROUTES=/admin/,/users/,/dashboard/,/api/secure/

Development (.env):

PROTECTED_ROUTES=/admin/,/users/

Quick Testing (no .env):

Uses start.php defaults:
- /dashboardexample/*
- /admin/*
- /users/*
- /moda

Wildcard Patterns

/admin/*        ? Matches /admin, /admin/users, /admin/settings/edit
/users/*        ? Matches /users, /users/profile, /users/123
/exact-route    ? Matches only /exact-route (no children)

When to Edit

Edit .env: Production security policies, specific project needs Edit start.php defaults: Default security for your project template

3?? Database Credentials Fallbacks

Location: /etc/Database.php

Priority Logic

1. Check .env for DB_* variables
   ? If DB_HOST exists: Use all .env DB_* vars ?
   ? If DB_HOST missing: Continue to fallback
   
2. Use ConfigDatabase.php values
   ? Returns fallback credentials

How It Works

// In Database.php
private function loadConfig()
{
    // Priority 1: .env file (production recommended)
    if (isset($_ENV['DB_HOST']) && !empty($_ENV['DB_HOST'])) {
        $this->host = $_ENV['DB_HOST'];
        $this->databaseName = $_ENV['DB_NAME'] ?? '';
        $this->username = $_ENV['DB_USER'] ?? '';
        $this->password = $_ENV['DB_PASS'] ?? '';
        $this->port = $_ENV['DB_PORT'] ?? 3306;
        $this->charset = $_ENV['DB_CHARSET'] ?? 'utf8mb4';
    } else {
        // Priority 2: ConfigDatabase.php (fallback)
        $this->host = ConfigDatabase::get('db.host');
        $this->databaseName = ConfigDatabase::get('db.name');
        $this->username = ConfigDatabase::get('db.user');
        $this->password = ConfigDatabase::get('db.pass');
        $this->port = ConfigDatabase::get('db.port', 3306);
        $this->charset = ConfigDatabase::get('db.charset', 'utf8mb4');
    }
}

Environment Variables

# .env database configuration (production)
DB_HOST=prod-server.com
DB_NAME=production_db
DB_USER=prod_user
DB_PASS=secure_password_here
DB_PORT=3306
DB_CHARSET=utf8mb4

Used For

  • ? PDO database connections
  • ? Model database operations
  • ? Migration scripts
  • ? Seed data scripts

Configuration Examples

Production (.env):

DB_HOST=mysql.production.com
DB_NAME=prod_database
DB_USER=prod_user
DB_PASS=strong_password_123
DB_PORT=3306
DB_CHARSET=utf8mb4

Development (.env):

DB_HOST=localhost
DB_NAME=dev_database
DB_USER=root
DB_PASS=
DB_PORT=3306

Quick Testing (ConfigDatabase.php fallback):

// /etc/ConfigDatabase.php
return [
    'db.host' => 'localhost',
    'db.name' => 'test_db',
    'db.user' => 'root',
    'db.pass' => '',
    'db.port' => 3306,
    'db.charset' => 'utf8mb4'
];

Security Best Practices

? Production: - ? Use .env file (not committed to Git) - ? Strong passwords - ? Limited user privileges - ? Encrypted connections if possible

? Development: - ? Use ConfigDatabase.php with dummy data - ? Never commit real credentials - ? Use different credentials than production

When to Edit

Edit .env: Production, staging, any real database Edit ConfigDatabase.php: Development defaults, local testing

4?? Session Configuration Fallbacks

Location: /etc/Config.php (line 215)

Configuration Logic

Session cookie parameters use array fallback with hardcoded defaults:

$sessionConfig = self::get('session', []);
if (isset($sessionConfig['name'])) {
    session_name($sessionConfig['name']);
}

session_set_cookie_params([
    'lifetime' => $sessionConfig['lifetime'] ?? 3600,      // Default: 1 hour
    'secure' => $sessionConfig['secure'] ?? false,         // Default: HTTP allowed
    'httponly' => $sessionConfig['httponly'] ?? true,      // Default: JS blocked
    'samesite' => 'Strict'                                 // Always Strict
]);

session_start();

Priority Logic

1. Config::get('session') from ConfigManager (loaded from .env)
   ? (if not set)
2. Hardcoded defaults in session_set_cookie_params()
   - lifetime: 3600 (1 hour)
   - secure: false (HTTP allowed)
   - httponly: true (JavaScript cannot access)
   - samesite: 'Strict' (no third-party cookies)

Configuration Examples

.env Configuration (Production):

SESSION_LIFETIME=7200                # 2 hours
SESSION_COOKIE=myapp_session
SESSION_SECURE=true                  # HTTPS only
SESSION_HTTP_ONLY=true               # Block JavaScript access
SESSION_SAME_SITE=strict

Result: Secure, long-lasting sessions for production use

.env Configuration (Development):

SESSION_LIFETIME=86400               # 24 hours (stay logged in)
SESSION_SECURE=false                 # HTTP allowed

Result: Developer-friendly with long sessions on localhost

No Configuration (Fallback): - Lifetime: 3600 seconds (1 hour) - Secure: false (works on HTTP) - HTTPOnly: true (XSS protection) - SameSite: Strict (CSRF protection)

When to Edit

Edit .env: To customize session behavior per environment Fallback: Secure defaults work for most development cases

5?? Security & Middleware Fallbacks

Location: /etc/Start.php (lines 158-192)

Configuration Logic

Security features use ConfigManager::get() with hardcoded defaults:

// CORS Support
if (ConfigManager::get('app.cors.enabled', false)) {
    $corsConfig = ConfigManager::get('app.cors', []);
    $middlewareManager->addGlobal(new CorsMiddleware($corsConfig));
}

// CSRF Protection
if ($method === 'POST' && ConfigManager::get('security.csrf_protection', true)) {
    $token = $_POST['csrf_token'] ?? '';
    if (!Security::validateCsrf($token)) {
        http_response_code(403);
        echo 'CSRF token validation failed';
        return false;
    }
}

// Rate Limiting
$identifier = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
$limit = ConfigManager::get('security.rate_limit', 100);

if (!Security::rateLimit($identifier, $limit)) {
    http_response_code(429);
    echo 'Rate limit exceeded';
    return false;
}

Priority Logic

1. .env variables loaded into ConfigManager
   ? (if not set)
2. ConfigManager::get() default parameter
   - app.cors.enabled: false (CORS disabled)
   - app.cors: [] (empty config)
   - security.csrf_protection: true (CSRF enabled)
   - security.rate_limit: 100 (requests limit)

Configuration Examples

.env Configuration (Production):

# CORS Settings
CORS_ENABLED=true
CORS_ALLOWED_ORIGINS=https://yourdomain.com,https://api.yourdomain.com
CORS_ALLOWED_METHODS=GET,POST,PUT,DELETE
CORS_ALLOWED_HEADERS=Content-Type,Authorization

# Security Settings
CSRF_PROTECTION=true                 # Always enabled in production
RATE_LIMIT=60                        # 60 requests per window

Result: Strict security with CORS for specific origins

.env Configuration (Development):

# CORS Settings
CORS_ENABLED=true
CORS_ALLOWED_ORIGINS=*               # Allow all origins

# Security Settings
CSRF_PROTECTION=false                # Easier API testing
RATE_LIMIT=1000                      # High limit for development

Result: Relaxed for development, easier testing

No Configuration (Fallback): - CORS: Disabled (no cross-origin requests) - CSRF: Enabled (security by default) - Rate Limit: 100 requests (reasonable default)

When to Edit

Edit .env: - Enable CORS for frontend-backend separation - Adjust rate limits per environment - Disable CSRF for API-only testing (not recommended for production)

Fallback: Secure defaults protect against common attacks

? Troubleshooting Configuration Conflicts

Problem: Settings not being applied

Check in this order:

  1. .env file (highest priority) - Location: `/etc/.env` - Is the file present? - Are variables correctly named? - Are there typos in variable names?
  2. Config.php $fallbacks (path/domain) - Location: `/etc/Config.php` - Lines: ~30-33 - Check `site_path` and `domain_name` values
  3. Config.php session defaults (session behavior) - Location: `/etc/Config.php` - Line: ~215 - Check session_set_cookie_params()
  4. start.php $defaultProtectedRoutes (auth routes) - Location: `/etc/start.php` - Lines: ~40-46 - Check route patterns match your needs
  5. start.php security settings (CORS, CSRF, rate limit) - Location: `/etc/start.php` - Lines: ~158-192 - Check ConfigManager::get() defaults
  6. ConfigDatabase.php (database) - Location: `/etc/ConfigDatabase.php` - Check all `db.*` keys

Common Issues

Issue 1: Wrong BASE_URL

Symptom: Links broken, assets not loading, routing fails

Solution:

1. Check .env: SITE_PATH and DOMAIN_NAME
2. If .env missing: Check Config.php $fallbacks
3. Verify no trailing slash in DOMAIN_NAME
4. Verify SITE_PATH starts with / or is empty

Issue 2: Routes not protected

Symptom: Can access admin without login

Solution:

1. Check .env: PROTECTED_ROUTES (comma-separated)
2. If .env missing: Check start.php $defaultProtectedRoutes
3. Verify wildcard patterns: /admin/not /admin
4. Check AuthMiddleware is registered

Issue 3: Database connection fails

Symptom: "Database could not be connected" error

Solution:

1. Check .env: All DB_* variables present
2. If .env missing: Check ConfigDatabase.php values
3. Verify database server is running
4. Test credentials with MySQL client
5. Check firewall/port access

Issue 4: Session not persisting

Symptom: User logs out immediately, session data lost

Solution:

1. Check .env: SESSION_LIFETIME, SESSION_SECURE
2. If .env missing: Defaults to 3600 seconds (1 hour)
3. For HTTPS sites: Set SESSION_SECURE=true in .env
4. Check session_set_cookie_params() in Config.php line 215
5. Verify cookies are enabled in browser

Issue 5: CORS blocking requests

Symptom: Frontend can't connect to backend API

Solution:

1. Check .env: CORS_ENABLED=true
2. Set CORS_ALLOWED_ORIGINS in .env
3. Default: CORS disabled (fallback)
4. Check ConfigManager::get('app.cors.enabled', false) in Start.php
5. For development: Use CORS_ALLOWED_ORIGINS=*

Debug Mode

Enable debug mode to see configuration values:

// In etc/.env
APP_ENV=development
DEBUG=true

Then check which config source is being used:

// Temporary debugging code
echo "Site Path Source: " . (isset($_ENV['SITE_PATH']) ? '.env' : 'Config.php fallback');
echo "DB Source: " . (isset($_ENV['DB_HOST']) ? '.env' : 'ConfigDatabase.php fallback');

? Configuration Strategy

Development Workflow

Day 1 - Quick Start:

1. Install upMVC
2. Don't create .env yet
3. Framework uses all fallbacks
4. Start coding immediately ?

Day 2 - Add Database:

1. Create .env file
2. Add only DB_* variables
3. Rest uses fallbacks
4. Database now connected ?

Day 3 - Custom Config:

1. Add SITE_PATH to .env
2. Add PROTECTED_ROUTES to .env
3. All custom, no fallbacks ?

Deployment Strategy

Development: - Use ConfigDatabase.php with local DB - Use Config.php fallbacks for paths - Use start.php default routes

Staging: - Create .env with staging DB credentials - Set SITE_PATH if in subfolder - Set PROTECTED_ROUTES for testing

Production: - Complete .env with all settings - Secure DB credentials - Custom protected routes - Never commit .env to Git!

? Best Practices

? DO:

  1. Use .env for production - Secure, not in Git
  2. Keep fallbacks as sensible defaults - For quick dev setup
  3. Document your .env variables - Team knows what to set
  4. Use different credentials per environment - Dev ? Production
  5. Version control fallback files - Team shares defaults

? DON'T:

  1. Commit .env to Git - Security risk!
  2. Use production credentials in fallbacks - Security risk!
  3. Rely on fallbacks in production - Use .env instead
  4. Mix configuration sources - Confusing to debug
  5. Hardcode paths in code - Use Config methods

? Related Documentation

? Quick Reference

Check Current Configuration

// In your code, check what's being used:

// Paths
echo Config::getSitePath();      // From .env or Config.php
echo Config::getDomainName();    // From .env or Config.php

// Protected Routes
$start = new Start();
$routes = $start->getProtectedRoutes();  // From .env or start.php
print_r($routes);

// Database
$db = new Database();
// Check connection success
$conn = $db->getConnection();
if ($conn) {
    echo "DB connected!";  // From .env or ConfigDatabase.php
}

.env Template

# Application
SITE_PATH=/upMVC
DOMAIN_NAME=http://localhost
APP_ENV=development
APP_DEBUG=true

# Database
DB_HOST=localhost
DB_NAME=your_database
DB_USER=your_username
DB_PASS=your_password
DB_PORT=3306
DB_CHARSET=utf8mb4

# Security & Routes
PROTECTED_ROUTES=/admin/,/users/,/dashboard/*
CSRF_PROTECTION=true
RATE_LIMIT=100

# Session Configuration
SESSION_LIFETIME=3600
SESSION_COOKIE=upmvc_session
SESSION_SECURE=false
SESSION_HTTP_ONLY=true
SESSION_SAME_SITE=strict

# CORS Configuration
CORS_ENABLED=false
CORS_ALLOWED_ORIGINS=https://yourdomain.com
CORS_ALLOWED_METHODS=GET,POST,PUT,DELETE
CORS_ALLOWED_HEADERS=Content-Type,Authorization

Last Updated: October 2025 upMVC Version: 1.4.x+