What's Actually Happening

Your PHP application crashes with a fatal error indicating that you're attempting to declare a class or function that has already been defined earlier in the script execution. This occurs when the same file is included multiple times, when different files define classes or functions with the same name without namespaces, when using both procedural includes and Composer autoloading for the same class, or when conditional declarations happen in an inconsistent manner.

The error immediately terminates script execution, preventing your application from running. This commonly happens in applications that haven't migrated to modern autoloading, in legacy code with complex include hierarchies, when integrating multiple libraries that have naming conflicts, or during refactoring when moving to namespace-based organization.

The Error You'll See

``` Fatal error: Cannot redeclare class UserService in /var/www/html/services/UserService.php on line 5

Fatal error: Cannot redeclare function format_date() (previously declared in /var/www/includes/helpers.php:23) in /var/www/app/helpers.php on line 15

Fatal error: Cannot declare class App\Models\User, because the name is already in use in /var/www/app/Models/User.php on line 7

Fatal error: Cannot redeclare class Database (previously declared in /var/www/lib/Database.php:3) in /var/www/classes/Database.php on line 2

PHP Fatal error: Cannot redeclare count_words() (previously declared in /var/www/html/functions.php:45) in /var/www/html/utils.php on line 12

Fatal error: Cannot redeclare class Config in /var/www/config/Config.php:4

Fatal error: Cannot use App\Models\User as User because the name is already in use

Fatal error: Cannot declare class Symfony\Component\HttpFoundation\Request, because the name is already in use

[08-Apr-2026 17:00:15 UTC] PHP Fatal error: Cannot redeclare class Product in /var/www/models/Product.php on line 8 Stack trace: #0 /var/www/html/index.php(15): include() #1 {main} ```

Why This Happens

  1. 1.Multiple includes of same file: Using include or require instead of include_once or require_once causes the same file to be loaded multiple times, attempting to redeclare everything in it.
  2. 2.Include chains: File A includes file B, which includes file C. But file A also directly includes file C, causing double loading. Complex dependency chains often have these hidden duplicates.
  3. 3.Same name without namespaces: Multiple files define classes or functions with the same simple name without using namespaces to differentiate them, causing naming collisions.
  4. 4.Mixed autoloading and manual includes: Composer autoload loads a class, then your code also manually includes the same file, causing the redeclaration.
  5. 5.Conditional includes gone wrong: Files included conditionally in ways that sometimes result in double-loading, especially when conditions overlap or change during execution.
  6. 6.Trait conflicts: Two traits used in the same class define methods with the same name without resolution, causing the "cannot redeclare" equivalent.
  7. 7.Interface and class name collision: An interface and a class share the same name in the same namespace.
  8. 8.Case sensitivity issues: On case-insensitive file systems (Windows, macOS), User.php and user.php refer to the same file, but PHP class names are case-insensitive, causing apparent redeclarations.
  9. 9.Caching issues: OPcache or other caches serving stale definitions alongside new ones.
  10. 10.Copy-paste errors: Accidentally duplicating class or function definitions in the same file or across files.

Step 1: Identify Where Redeclaration Occurs

Find the source of the conflict:

```bash # Search for the class/function being declared grep -rn "class UserService" /var/www/html/ grep -rn "function format_date" /var/www/html/

# Find all files that include/require the problematic file grep -rn "include.*UserService" /var/www/html/ grep -rn "require.*helpers.php" /var/www/html/

# Trace include paths php -r " \$files = get_included_files(); foreach (\$files as \$f) { echo \$f . '\n'; } " 2>/dev/null || echo "Script didn't run successfully"

# Create debugging script cat > /tmp/trace_includes.php << 'EOF' <?php // Track all includes $includedFiles = [];

// Override include functions stream_wrapper_unregister('file'); stream_wrapper_register('file', 'IncludeTracer');

class IncludeTracer { private $context;

public function stream_open($path, $mode, $options, &$opened_path) { global $includedFiles;

if (file_exists($path)) { if (isset($includedFiles[$path])) { echo "DUPLICATE INCLUDE: $path\n"; echo "First included from: " . $includedFiles[$path] . "\n"; echo "Now included from: " . debug_backtrace()[1]['file'] . "\n\n"; } else { $includedFiles[$path] = debug_backtrace()[1]['file']; } }

$this->context = fopen($path, $mode); return $this->context !== false; }

public function stream_read($count) { return fread($this->context, $count); }

public function stream_eof() { return feof($this->context); }

public function stream_close() { return fclose($this->context); }

public function stream_stat() { return fstat($this->context); } }

// Now include your main file require '/var/www/html/index.php'; EOF

# Check for class existence before declaration cat > /tmp/check_class.php << 'EOF' <?php // Check which class already exists if (class_exists('UserService', false)) { $reflector = new ReflectionClass('UserService'); echo "Class UserService already defined in: " . $reflector->getFileName() . "\n"; echo "Line: " . $reflector->getStartLine() . "\n"; }

if (function_exists('format_date')) { $reflector = new ReflectionFunction('format_date'); echo "Function format_date already defined in: " . $reflector->getFileName() . "\n"; echo "Line: " . $reflector->getStartLine() . "\n"; } EOF

php /tmp/check_class.php ```

Debug with detailed backtrace:

```php <?php // Add this at the start of the file causing the error register_shutdown_function(function() { $error = error_get_last();

if ($error && strpos($error['message'], 'redeclare') !== false) { // Parse the error to get class/function name preg_match('/Cannot (?:redeclare|declare) (?:class|function) ([^\s(]+)/', $error['message'], $matches); $name = $matches[1] ?? 'unknown';

echo "Redeclaration detected for: $name\n";

if (class_exists($name, false)) { $ref = new ReflectionClass($name); echo "Originally defined in: " . $ref->getFileName() . ":" . $ref->getStartLine() . "\n"; }

if (function_exists($name)) { $ref = new ReflectionFunction($name); echo "Originally defined in: " . $ref->getFileName() . ":" . $ref->getStartLine() . "\n"; }

// Show backtrace echo "\nBacktrace:\n"; debug_print_backtrace(); } }); ?> ```

Step 2: Use Include_once and Require_once

Replace include/require with their _once counterparts:

```php <?php // BAD: May include the same file multiple times include 'config/database.php'; include 'helpers/functions.php'; include 'models/User.php';

// GOOD: Only includes if not already loaded include_once 'config/database.php'; include_once 'helpers/functions.php'; include_once 'models/User.php';

// BETTER: Use require_once for critical files require_once 'config/database.php'; // Script dies if file missing require_once 'helpers/functions.php'; require_once 'models/User.php';

// Create a helper for consistent includes function safeInclude($file) { static $included = [];

$realpath = realpath($file);

if ($realpath === false) { throw new RuntimeException("File not found: $file"); }

if (isset($included[$realpath])) { return true; // Already included }

$included[$realpath] = true; require_once $file;

return true; }

// Usage safeInclude('config/database.php'); safeInclude('models/User.php');

// Class loader that prevents redeclaration class ClassLoader { private static $loaded = [];

public static function load($class, $file) { if (isset(self::$loaded[$class])) { return true; }

if (!file_exists($file)) { throw new RuntimeException("Class file not found: $file"); }

if (class_exists($class, false)) { self::$loaded[$class] = true; return true; }

require_once $file; self::$loaded[$class] = true;

return true; } }

// Usage ClassLoader::load('User', 'models/User.php'); ClassLoader::load('Product', 'models/Product.php'); ?> ```

Step 3: Migrate to Composer Autoloading

Replace manual includes with autoloading:

json
{
    "autoload": {
        "psr-4": {
            "App\\": "src/",
            "App\\Models\\": "src/Models/",
            "App\\Services\\": "src/Services/",
            "App\\Controllers\\": "src/Controllers/"
        },
        "classmap": [
            "legacy/classes/"
        ],
        "files": [
            "app/helpers.php",
            "app/functions.php"
        ]
    }
}

```bash # Generate autoload files composer dump-autoload --optimize

# Use in your application # bootstrap.php <?php require_once __DIR__ . '/vendor/autoload.php';

// No more manual includes needed! // Classes are loaded automatically when used $user = new App\Models\User(); $service = new App\Services\UserService(); ```

```php <?php // Before: Manual includes everywhere require_once 'models/User.php'; require_once 'models/Product.php'; require_once 'services/UserService.php'; require_once 'services/ProductService.php';

$user = new User(); $service = new UserService();

// After: Just use autoload // At the start of your application require_once __DIR__ . '/vendor/autoload.php';

// Use namespaced classes use App\Models\User; use App\Services\UserService;

$user = new User(); $service = new UserService();

// Or with full namespace $user = new App\Models\User();

// Convert legacy code to use namespaces // Old: models/User.php <?php class User { // ... }

// New: src/Models/User.php <?php namespace App\Models;

class User { // ... } ?> ```

Step 4: Use Namespaces to Avoid Name Collisions

Organize code with namespaces:

```php <?php // PROBLEM: Two classes with same name // models/User.php class User { public function getName() { return 'Model User'; } }

// admin/models/User.php class User { // ERROR: Cannot redeclare class User public function getName() { return 'Admin User'; } }

// SOLUTION: Use namespaces

// src/Models/User.php namespace App\Models;

class User { public function getName() { return 'Model User'; } }

// src/Admin/Models/User.php namespace App\Admin\Models;

class User { public function getName() { return 'Admin User'; } }

// Usage use App\Models\User as ModelUser; use App\Admin\Models\User as AdminUser;

$modelUser = new ModelUser(); $adminUser = new AdminUser();

// Or use full namespace $modelUser = new App\Models\User(); $adminUser = new App\Admin\Models\User();

// Functions also benefit from namespaces namespace App\Helpers;

function format_date($timestamp) { return date('Y-m-d', $timestamp); }

// Usage echo \App\Helpers\format_date(time());

// Or import use function App\Helpers\format_date; echo format_date(time());

// Constants in namespaces namespace App\Config;

const VERSION = '1.0.0'; const MAX_ITEMS = 100;

// Usage echo \App\Config\VERSION;

// Or import use const App\Config\VERSION; echo VERSION; ?> ```

Step 5: Fix Trait Conflicts

Handle trait method name collisions:

```php <?php // PROBLEM: Two traits with same method name trait Loggable { public function log($message) { echo "[LOG] $message\n"; }

public function save() { echo "Loggable save\n"; } }

trait Auditable { public function log($message) { echo "[AUDIT] $message\n"; }

public function save() { echo "Auditable save\n"; } }

// This will cause a conflict error class User { use Loggable, Auditable; // Fatal error: Trait method conflict }

// SOLUTION 1: Use insteadof to choose which to use class User { use Loggable, Auditable { Loggable::log insteadof Auditable; // Use Loggable's log Auditable::save insteadof Loggable; // Use Auditable's save

// Or use both with aliases Auditable::log as auditLog; } }

$user = new User(); $user->log('test'); // Uses Loggable::log $user->auditLog('test'); // Uses Auditable::log with alias $user->save(); // Uses Auditable::save

// SOLUTION 2: Use aliases for all conflicting methods class Product { use Loggable, Auditable { Loggable::log insteadof Auditable; Loggable::save insteadof Auditable;

Auditable::log as auditLog; Auditable::save as auditSave; } }

$product = new Product(); $product->log('message'); $product->auditLog('audit message'); $product->save(); $product->auditSave();

// SOLUTION 3: Override in the class class Order { use Loggable, Auditable { Loggable::log insteadof Auditable; }

// Override the conflicting method public function log($message) { // Custom implementation parent::log('[ORDER] ' . $message); // Can't call trait directly echo "[CUSTOM] $message\n"; } }

// Helper to detect trait conflicts function detectTraitConflicts($traits) { $methods = []; $conflicts = [];

foreach ($traits as $trait) { $reflection = new ReflectionClass($trait); foreach ($reflection->getMethods() as $method) { $name = $method->getName(); if (isset($methods[$name])) { $conflicts[$name][] = $trait; } else { $methods[$name] = $trait; } } }

return $conflicts; }

// Check for conflicts $conflicts = detectTraitConflicts([Loggable::class, Auditable::class]); if (!empty($conflicts)) { echo "Conflicting methods:\n"; foreach ($conflicts as $method => $traits) { echo " $method: " . implode(', ', $traits) . "\n"; } } ?> ```

Step 6: Handle Conditional Declarations

Fix issues with conditionally declared classes/functions:

```php <?php // PROBLEM: Conditional class declaration if (!class_exists('User')) { class User { // This might cause issues if condition logic changes } }

// PROBLEM: Conditional function declaration if (!function_exists('helper')) { function helper() { // ... } }

// These patterns cause issues because: // 1. The condition might be evaluated differently on subsequent includes // 2. Makes autoloading impossible // 3. Causes inconsistent behavior

// SOLUTION 1: Use interfaces and concrete implementations interface UserInterface { public function getId(); }

class StandardUser implements UserInterface { public function getId() { return $this->id; } }

class AdminUser implements UserInterface { public function getId() { return 'admin_' . $this->id; } }

// Factory to create appropriate implementation class UserFactory { public static function create($type) { switch ($type) { case 'admin': return new AdminUser(); default: return new StandardUser(); } } }

// SOLUTION 2: Use configuration instead of conditions class Config { private static $userClass = StandardUser::class;

public static function setUserClass($class) { if (!class_exists($class)) { throw new InvalidArgumentException("Class $class does not exist"); } self::$userClass = $class; }

public static function createUser() { $class = self::$userClass; return new $class(); } }

// Configure at runtime Config::setUserClass(AdminUser::class); $user = Config::createUser();

// SOLUTION 3: Use strategy pattern interface LoggerInterface { public function log($message); }

class FileLogger implements LoggerInterface { public function log($message) { file_put_contents('app.log', $message . "\n", FILE_APPEND); } }

class DatabaseLogger implements LoggerInterface { public function log($message) { // Log to database } }

class LoggerFactory { public static function create(): LoggerInterface { if (getenv('LOG_TYPE') === 'database') { return new DatabaseLogger(); } return new FileLogger(); } }

// SOLID approach - no conditional declarations $logger = LoggerFactory::create();

// If you MUST use conditional function declarations // Put them in separate files

// functions_standard.php function formatDate($timestamp) { return date('Y-m-d', $timestamp); }

// functions_extended.php function formatDate($timestamp) { return date('F j, Y', $timestamp); }

// Load appropriate file based on configuration $functionFile = $extended ? 'functions_extended.php' : 'functions_standard.php'; require_once $functionFile;

// Better: Use a class with different implementations interface DateFormatterInterface { public function format($timestamp); }

class StandardDateFormatter implements DateFormatterInterface { public function format($timestamp) { return date('Y-m-d', $timestamp); } }

class ExtendedDateFormatter implements DateFormatterInterface { public function format($timestamp) { return date('F j, Y', $timestamp); } } ?> ```

Step 7: Detect and Fix Copy-Paste Errors

Find accidental duplications:

```php <?php // Script to find duplicate class/function declarations class DuplicationDetector { private $classes = []; private $functions = []; private $duplicates = [];

public function scanDirectory($dir) { $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($dir) );

foreach ($iterator as $file) { if ($file->getExtension() === 'php') { $this->scanFile($file->getPathname()); } }

return $this->duplicates; }

private function scanFile($filepath) { $content = file_get_contents($filepath); $tokens = token_get_all($content);

$namespace = ''; $inClass = false; $inFunction = false; $braceLevel = 0;

foreach ($tokens as $i => $token) { if (!is_array($token)) { if ($token === '{') $braceLevel++; if ($token === '}') $braceLevel--; continue; }

// Track namespace if ($token[0] === T_NAMESPACE) { $namespace = ''; for ($j = $i + 1; $j < count($tokens); $j++) { if ($tokens[$j] === ';') break; if (is_array($tokens[$j]) && $tokens[$j][0] === T_STRING) { $namespace .= ($namespace ? '\\' : '') . $tokens[$j][1]; } } }

// Track class declarations if ($token[0] === T_CLASS && !$inClass) { for ($j = $i + 1; $j < count($tokens); $j++) { if (is_array($tokens[$j]) && $tokens[$j][0] === T_STRING) { $className = $tokens[$j][1]; $fullName = $namespace ? "$namespace\\$className" : $className;

if (isset($this->classes[$fullName])) { $this->duplicates['class'][$fullName][] = [ 'file' => $filepath, 'line' => $token[2], 'previous' => $this->classes[$fullName] ]; } else { $this->classes[$fullName] = [ 'file' => $filepath, 'line' => $token[2] ]; } break; } } $inClass = true; }

// Track function declarations if ($token[0] === T_FUNCTION && !$inClass && $braceLevel === 0) { for ($j = $i + 1; $j < count($tokens); $j++) { if (is_array($tokens[$j]) && $tokens[$j][0] === T_STRING) { $funcName = $tokens[$j][1]; $fullName = $namespace ? "$namespace\\$funcName" : $funcName;

if (isset($this->functions[$fullName])) { $this->duplicates['function'][$fullName][] = [ 'file' => $filepath, 'line' => $token[2], 'previous' => $this->functions[$fullName] ]; } else { $this->functions[$fullName] = [ 'file' => $filepath, 'line' => $token[2] ]; } break; } } } } }

public function getClasses() { return $this->classes; }

public function getFunctions() { return $this->functions; } }

// Usage $detector = new DuplicationDetector(); $duplicates = $detector->scanDirectory('/var/www/html');

if (!empty($duplicates)) { echo "DUPLICATES FOUND:\n\n";

if (!empty($duplicates['class'])) { echo "Duplicate Classes:\n"; foreach ($duplicates['class'] as $name => $instances) { echo " $name:\n"; foreach ($instances as $instance) { echo " - {$instance['file']}:{$instance['line']}\n"; echo " Previously: {$instance['previous']['file']}:{$instance['previous']['line']}\n"; } } }

if (!empty($duplicates['function'])) { echo "\nDuplicate Functions:\n"; foreach ($duplicates['function'] as $name => $instances) { echo " $name:\n"; foreach ($instances as $instance) { echo " - {$instance['file']}:{$instance['line']}\n"; echo " Previously: {$instance['previous']['file']}:{$instance['previous']['line']}\n"; } } } } else { echo "No duplicates found.\n"; } ?> ```

Step 8: Handle Mixed Autoloading

Fix conflicts between manual includes and autoloading:

```php <?php // PROBLEM: Both autoload and manual include

// composer.json defines autoload // Then you also manually include require_once 'src/Services/UserService.php'; // Manual include

$user = new UserService(); // Autoload also tries to load this

// SOLUTION 1: Only use autoload // Remove all manual includes, rely solely on Composer autoload require_once 'vendor/autoload.php';

$user = new App\Services\UserService(); // Autoloaded

// SOLUTION 2: If you must use manual includes, unregister autoload for specific paths $autoloaders = spl_autoload_functions(); foreach ($autoloaders as $autoloader) { if (is_array($autoloader) && $autoloader[0] instanceof Composer\Autoload\ClassLoader) { // Found Composer autoloader // Can modify its class map if needed } }

// SOLUTION 3: Use classmap for legacy code // composer.json { "autoload": { "psr-4": { "App\\": "src/" }, "classmap": [ "legacy/", "includes/" ] } }

// Then regenerate autoload // composer dump-autoload

// SOLUTION 4: Check if class exists before including if (!class_exists('UserService')) { require_once 'services/UserService.php'; }

// Better with autoloader registration class LegacyLoader { public static function register() { spl_autoload_register([self::class, 'load']); }

public static function load($class) { // Map class to file $map = [ 'UserService' => 'services/UserService.php', 'ProductService' => 'services/ProductService.php', 'Database' => 'lib/Database.php', ];

if (isset($map[$class])) { $file = __DIR__ . '/' . $map[$class]; if (file_exists($file) && !class_exists($class, false)) { require $file; } } } }

// Register before Composer's autoloader LegacyLoader::register(); require 'vendor/autoload.php';

// Now both legacy and new classes load correctly $legacy = new UserService(); // Loaded by LegacyLoader $modern = new App\Services\User(); // Loaded by Composer ?> ```

Step 9: Fix Case Sensitivity Issues

Handle case sensitivity on different operating systems:

```php <?php // Case sensitivity issues // On Windows/macOS (case-insensitive filesystem): // User.php and user.php are the same file // But PHP class names are case-insensitive

// PROBLEM: // File: models/User.php class User {}

// File: models/user.php (same file on Windows!) class User {} // Redeclaration!

// And: $user = new User(); // Works $user = new user(); // Same class! $user = new USER(); // Same class!

// SOLUTION 1: Use consistent casing // Always use PascalCase for class names // File name should match class name exactly

// UserService.php class UserService {}

// SOLUTION 2: Enforce naming conventions with script function checkNamingConventions($dir) { $issues = [];

$iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($dir) );

foreach ($iterator as $file) { if ($file->getExtension() !== 'php') continue;

$filename = $file->getBasename('.php'); $filepath = $file->getPathname();

$content = file_get_contents($filepath);

// Find class declarations if (preg_match('/class\s+(\w+)/', $content, $match)) { $className = $match[1];

if ($filename !== $className) { $issues[] = [ 'file' => $filepath, 'filename' => $filename, 'classname' => $className, 'issue' => 'Filename does not match class name' ]; }

// Check for proper casing $expected = ucfirst($className); if ($className !== $expected && !preg_match('/^[A-Z][a-zA-Z0-9]*$/', $className)) { $issues[] = [ 'file' => $filepath, 'classname' => $className, 'issue' => 'Class name not in PascalCase' ]; } }

// Find function declarations (global scope) if (preg_match('/^(?!.*class)(?=.*function\s+(\w+))/m', $content, $match)) { $funcName = $match[1];

if (!preg_match('/^[a-z][a-zA-Z0-9]*$/', $funcName)) { $issues[] = [ 'file' => $filepath, 'function' => $funcName, 'issue' => 'Function name not in camelCase' ]; } } }

return $issues; }

$issues = checkNamingConventions('src/'); foreach ($issues as $issue) { echo "{$issue['file']}: {$issue['issue']}\n"; }

// SOLUTION 3: Use autoload strictly // With PSR-4, the autoloader enforces proper naming // Just follow the standard and let Composer handle it

// SOLUTION 4: Add checks in bootstrap function validateClassLoading($className) { // Log case mismatches $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); $callingFile = $backtrace[1]['file'] ?? 'unknown';

// Check if class name matches expected format if (!preg_match('/^[A-Z][a-zA-Z0-9_]*$/', $className)) { error_log("Class name '$className' may have casing issues. Called from $callingFile"); } }

spl_autoload_register('validateClassLoading', true, true); ?> ```

Step 10: Implement Preventive Measures

Set up checks and balances:

```php <?php // bootstrap.php - Preventive measures

// 1. Track loaded classes class LoadedClassTracker { private static $classes = [];

public static function track($class, $file) { if (isset(self::$classes[$class])) { throw new RuntimeException( "Class $class already loaded from " . self::$classes[$class] . ", attempted to load from $file" ); } self::$classes[$class] = $file; }

public static function getLoadedClasses() { return self::$classes; } }

// 2. Custom autoloader with tracking class SafeAutoloader { private static $map = [];

public static function register() { spl_autoload_register([self::class, 'load'], true, true); }

public static function addNamespace($namespace, $baseDir) { self::$map[$namespace] = $baseDir; }

public static function load($class) { // Check if already loaded if (class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false)) { return true; }

// Find file foreach (self::$map as $namespace => $dir) { if (strpos($class, $namespace) === 0) { $relativeClass = substr($class, strlen($namespace)); $file = $dir . str_replace('\\', '/', $relativeClass) . '.php';

if (file_exists($file)) { LoadedClassTracker::track($class, $file); require $file; return true; } } }

return false; } }

// Register autoloader SafeAutoloader::register(); SafeAutoloader::addNamespace('App\\', __DIR__ . '/src/');

// 3. Validation in development if (getenv('APP_ENV') === 'development') { // Check for potential issues register_shutdown_function(function() { $error = error_get_last();

if ($error && strpos($error['message'], 'redeclare') !== false) { // Log detailed information $log = [ 'error' => $error['message'], 'file' => $error['file'], 'line' => $error['line'], 'included_files' => get_included_files(), 'loaded_classes' => LoadedClassTracker::getLoadedClasses(), ];

file_put_contents( __DIR__ . '/logs/redeclare_' . date('Y-m-d_His') . '.json', json_encode($log, JSON_PRETTY_PRINT) ); } }); }

// 4. Pre-flight check function preflightCheck() { $issues = [];

// Check if autoload exists if (!file_exists(__DIR__ . '/vendor/autoload.php')) { $issues[] = 'vendor/autoload.php not found. Run composer install'; }

// Check for common problematic patterns $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator(__DIR__ . '/src') );

foreach ($iterator as $file) { if ($file->getExtension() !== 'php') continue;

$content = file_get_contents($file->getPathname());

// Check for include/require without _once if (preg_match('/\b(include|require)\s*[\'"(]/', $content) && !preg_match('/\b(include|require)_once\s*[\'"(]/', $content)) { $issues[] = $file->getPathname() . ' uses include/require without _once'; }

// Check for class declarations without namespace if (preg_match('/^class\s+\w+/m', $content) && !preg_match('/^namespace\s+/', $content)) { $issues[] = $file->getPathname() . ' has class without namespace'; } }

return $issues; }

// Run checks in development if (getenv('APP_ENV') === 'development') { $issues = preflightCheck(); if (!empty($issues)) { trigger_error('Preflight issues found: ' . implode('; ', $issues), E_USER_WARNING); } }

// 5. CI/CD check script // Run this in your CI pipeline if (php_sapi_name() === 'cli' && isset($argv[1]) && $argv[1] === '--check') { echo "Running pre-deployment checks...\n";

$issues = preflightCheck();

if (empty($issues)) { echo "All checks passed!\n"; exit(0); } else { echo "Issues found:\n"; foreach ($issues as $issue) { echo " - $issue\n"; } exit(1); } } ?> ```

Checklist

StepActionVerified
1Identified source of redeclaration
2Replaced include with include_once/require_once
3Migrated to Composer autoloading
4Added proper namespaces
5Resolved trait conflicts
6Fixed conditional declarations
7Removed copy-paste duplications
8Resolved autoload/include conflicts
9Fixed case sensitivity issues
10Implemented preventive measures
11Tested all includes work correctly
12Verified in production environment

Verify the Fix

  1. 1.Test basic includes:
  2. 2.```php
  3. 3.<?php
  4. 4.// test_includes.php
  5. 5.require_once 'config.php';
  6. 6.require_once 'config.php'; // Should not cause error
  7. 7.require_once 'database.php';
  8. 8.echo "All includes successful\n";
  9. 9.?>
  10. 10.`
  11. 11.Verify autoloading works:
  12. 12.```bash
  13. 13.composer dump-autoload --optimize
  14. 14.php -r "
  15. 15.require 'vendor/autoload.php';
  16. 16.\$user = new App\Models\User();
  17. 17.echo 'Class loaded: ' . get_class(\$user) . '\n';
  18. 18."
  19. 19.`
  20. 20.Check for remaining duplicates:
  21. 21.```php
  22. 22.<?php
  23. 23.require 'DuplicationDetector.php';
  24. 24.$detector = new DuplicationDetector();
  25. 25.$duplicates = $detector->scanDirectory('src/');
  26. 26.var_dump($duplicates); // Should be empty
  27. 27.?>
  28. 28.`
  29. 29.Test class loading:
  30. 30.```php
  31. 31.<?php
  32. 32.require_once 'vendor/autoload.php';

// Try to load class twice (should work) $class1 = new App\Services\UserService(); $class2 = new App\Services\UserService();

echo "Both instances created successfully\n"; echo "Same class: " . (get_class($class1) === get_class($class2) ? 'Yes' : 'No') . "\n"; ?> ```

  1. 1.Run preflight check:
  2. 2.```bash
  3. 3.php bootstrap.php --check
  4. 4.`
  5. 5.Monitor production:
  6. 6.```bash
  7. 7.tail -f /var/log/php-fpm/error.log | grep -i "redeclare"
  8. 8.grep -c "Cannot redeclare" /var/log/php-fpm/error.log
  9. 9.`
  • [Fix PHP Class Not Found Autoload](/articles/fix-php-class-not-found-autoload)
  • [Fix PHP Namespace Declaration Error](/articles/fix-php-namespace-declaration-error)
  • [Fix PHP Composer Dependency Conflict](/articles/fix-php-composer-dependency-conflict)
  • [Fix Laravel Class Not Found](/articles/fix-laravel-class-not-found)
  • [Fix Symfony Service Already Exists](/articles/fix-symfony-service-already-exists)
  • [Fix WordPress Plugin Conflict](/articles/fix-wordpress-plugin-conflict)
  • [Fix Magento Module Rewrite Conflict](/articles/fix-magento-module-rewrite-conflict)
  • [Fix Drupal Module Hook Conflict](/articles/fix-drupal-module-hook-conflict)
  • [Fix PHP Trait Method Conflict](/articles/fix-php-trait-method-conflict)
  • [Fix PHP Interface Implementation Error](/articles/fix-php-interface-implementation-error)