Aikido

How to fix PHP autoload errors: matching class names to filenames

Bug Risk

Rule
Class name must match filename.
Many languages require class names
to match filenames exactly, or they'll
fail on case-sensitive filesystems (Linux).

Supported languages: PHP

Introduction

PHP's PSR-4 autoloading requires class names to match filenames exactly, including case. A class named UserRepository must be in UserRepository.php, not userrepository.php. This works on case-insensitive filesystems like Windows and macOS but breaks on Linux servers, causing "Class not found" errors in production.

Why it matters

Production failures: Mismatched names cause autoload failures on Linux servers where filesystems are case-sensitive. Code that works locally breaks in production, requiring emergency hotfixes and causing downtime.

PSR-4 compliance: Modern PHP frameworks rely on PSR-4 autoloading. Classes that don't follow naming conventions can't be autoloaded, breaking dependency injection, service containers, and framework features.

Code examples

❌ Non-compliant:

<?php
// File: userrepository.php

namespace App\Repositories;

class UserRepository
{
    public function findById($id)
    {
        return User::find($id);
    }

    public function save(User $user)
    {
        return $user->save();
    }
}

Why it's wrong: The class name is UserRepository but the filename is userrepository.php (lowercase). PSR-4 autoloader will look for UserRepository.php and fail to find it on case-sensitive Linux filesystems, causing fatal errors in production.

✅ Compliant:

<?php
// File: UserRepository.php

namespace App\Repositories;

class UserRepository
{
    public function findById($id)
    {
        return User::find($id);
    }

    public function save(User $user)
    {
        return $user->save();
    }
}

Why this matters: The filename UserRepository.php matches the class name UserRepository exactly, including case. PSR-4 autoloader can reliably locate and load the class on any filesystem, eliminating environment-specific failures and ensuring consistent behavior across development and production.

Conclusion

Enforce strict filename-to-class-name matching from the start of your project. Configure your IDE to automatically name files correctly when creating classes. Use automated checks in CI/CD pipelines to catch mismatches before deployment. The five minutes spent ensuring proper naming prevents hours of debugging production autoload failures.

FAQs

Got Questions?

Why does this work on Windows/macOS but fail on Linux?

Windows and macOS use case-insensitive filesystems by default (NTFS, APFS, HFS+). When PHP's autoloader requests UserRepository.php, these systems will return userrepository.php because they treat filenames as case-insensitive. Linux uses case-sensitive filesystems (ext4, xfs) where UserRepository.php and userrepository.php are completely different files. The autoloader fails because it looks for an exact match.

How do I find all class/filename mismatches in my codebase?

Write a script that scans PHP files, extracts class names using reflection or regex, and compares them to filenames. Many static analysis tools detect PSR-4 violations. In CI/CD, run Composer's autoloader validation with composer dump-autoload --optimize --strict-psr. This catches mismatches before deployment. Some IDEs like PhpStorm highlight PSR-4 violations during development.

What about traits, interfaces, and abstract classes?

The same rule applies. An interface named UserRepositoryInterface must be in UserRepositoryInterface.php. A trait named Timestampable requires Timestampable.php. Abstract classes follow the same pattern. PSR-4 treats all class-like structures identically. The filename must match the class/trait/interface name exactly, including case.

Can I use underscores or hyphens in filenames?

No for PSR-4 compliance. PHP class names can't contain hyphens or most special characters. Underscores are technically allowed in class names but discouraged by PSR standards. Stick to PascalCase for both class names and filenames: UserRepository, not User_Repository or user-repository. Consistency with PSR-4 conventions ensures framework compatibility.

What if I have multiple classes in one file?

Don't. PSR-4 requires one class per file with matching names. Multiple classes in a single file break autoloading because the autoloader expects a 1:1 relationship between class names and file paths. If you have tightly coupled classes, consider whether they should be inner classes, separate files, or refactored into a single cohesive class. One class per file is a fundamental PSR-4 requirement.

How do I handle legacy code that violates this rule?

Fix all mismatches before deploying to Linux servers, as mismatched files will cause immediate autoload failures in production. Use IDE refactoring tools that rename both class and file simultaneously. On macOS, case-only renames may require two git commits: first rename to a temporary name (UserRepository_temp.php), commit, then rename to the correct case (UserRepository.php). For large codebases, fix all violations in a dedicated PR, test thoroughly, then deploy. Update Composer's autoloader (composer dump-autoload) after renaming files.

Does namespace affect the filename?

Namespace affects the directory structure, not the filename itself. A class App\\Repositories\\UserRepository should be in app/Repositories/UserRepository.php (or src/Repositories/UserRepository.php depending on your PSR-4 root). The namespace maps to directories, and the class name maps to the filename. Both must follow PSR-4 conventions: namespace segments map to directories with matching case, class name maps to filename with matching case.

Get secure for free

Secure your code, cloud, and runtime in one central system.
Find and fix vulnerabilities fast automatically.

No credit card required | Scan results in 32secs.