Originally published on decentphp.dev — part of the Writing decent PHP course. View this lesson on the original site.

File and folder names are the table of contents for your codebase

Before any developer reads a line of your code, they read the file tree. Folder and file names should answer two questions at a glance:

  • "where does X live?"
  • "what kind of code lives in this part of the project?"

If the folder structure is organised by technical layer only (Controllers, Models, Helpers, Services), the answer to "where does billing logic live?" is "spread across all of them". If it is organised by feature or domain (Billing, Registration, Reporting), the answer is one folder.

Before

A typical "everything by layer" structure. Easy to set up, harder to navigate as the project grows.

src/
    Controllers/
        UserController.php
        OrderController.php
        StuffController.php
    Models/
        User.php
        Order.php
        Misc.php
    Services/
        UserService.php
        OrderService.php
        Helper.php
        Utils.php
    Helpers/
        functions.php
        common.php

Problems you can read straight off the tree:

  • to change registration, you touch UserController, UserService, User, and probably Helper too
  • there is a Helpers/ folder and a Helper class — duplication of the worst suffixes (see lesson 2.6)
  • StuffController, Misc, Utils, common.php — names with no commitment to a concept
  • nothing tells you where a new feature should go

After

The same code reorganised so each folder answers "what feature lives here?", with a small Shared/ area for code that genuinely crosses features.

src/
    Registration/
        RegisterUserController.php
        RegisterUserHandler.php
        SignupInputValidator.php
    Billing/
        ChargeCustomerController.php
        InvoiceRepository.php
        OrderTotalCalculator.php
    Reporting/
        MonthlySalesReport.php
        SalesReportRenderer.php
    Shared/
        Money.php
        EmailAddress.php

Now the file tree alone tells you:

  • where new registration code goes
  • which features touch billing
  • that Money and EmailAddress are reusable value objects, not feature-specific code
  • that there is no dumping ground — the lack of a Misc/ folder is intentional

Why this version is better

  • finding code is folder-level, not project-wide search
  • a feature change usually fits in one folder, which makes diffs and reviews smaller
  • adding a new feature means adding a new folder, not editing six existing ones
  • removing a feature is a rm -rf, not an archaeology dig

File naming rules that pay off

Rule Why it matters
One PHP class per file matches PSR-4 autoloading; the file name is the class name
File name = class name (case-sensitive) broken on case-insensitive macOS / case-sensitive Linux otherwise
PascalCase.php for class files e.g. OrderTotalCalculator.php
kebab-case for assets and docs e.g. signup-flow.md, order-receipt.css
Avoid catch-all files no functions.php, no helpers.php, no common.php
Avoid version numbers in file names use git history; OrderServiceV2.php rots fast

Folder naming rules that pay off

Rule Why it matters
Folder names are domain nouns Billing/, Registration/, not Stuff/, Misc/
Group by feature first, by type second Billing/Controllers/ is fine; Controllers/Billing/ is harder to navigate
Keep nesting shallow three levels is plenty for most apps
One folder per concept not two folders called Helpers/ and Utils/ doing the same thing
No abbreviations Reporting/ not Rpt/, Subscriptions/ not Subs/
Singular for concept folders, plural for collections Billing/ (the concept), Invoices/ (the collection of invoice classes)

Names to avoid

  • helpers/, utils/, common/, misc/, stuff/, lib/ — bins that turn into junk drawers
  • generic file names like index.php, script.php, class.php (outside framework entry points)
  • mixed casing in the same folder (User.php next to userprofile.php) — fragile across operating systems
  • duplicated concept names across folders (Auth/User.php and Profile/User.php referring to the same concept)

A small file/folder smell test

Stand up the folder tree in your head and ask:

  1. Could a new developer guess which folder a feature lives in without asking?
  2. Does any folder name contain Helper, Util, Common, or Misc?
  3. If I add a new feature next sprint, do I know exactly where it goes?

If the answer to (1) or (3) is no, or the answer to (2) is yes, the structure is doing less work for you than it should be.

From Writing decent PHP — Naming variables, functions, classes, and files well