Skip to content

PHP Tutorial Namespaces and Autoloading

Organizing Classes

Lesson 243 of 369 2 min read By Deepak Paswan Updated Oct 5, 2026

A growing project needs a clear layout. The standard rule is simple: the namespace mirrors the folder structure, and the file name equals the class name.

Text
PLAIN
my-app/
├── composer.json
├── public/
│   └── index.php
├── src/
│   ├── Model/
│   │   └── Product.php          App\Model\Product
│   ├── Service/
│   │   └── PriceCalculator.php  App\Service\PriceCalculator
│   └── Http/
│       └── ProductController.php  App\Http\ProductController
└── vendor/

The namespace App\ is mapped to the src/ folder. So App\Service\PriceCalculator lives in src/Service/PriceCalculator.php.

One class per file

Each class, interface, trait or enum gets its own file. The file name matches the type name exactly, including capital letters (important on Linux, where Product.php and product.php are different files).

src/Service/PriceCalculator.php
PHP
<?php

declare(strict_types=1);

namespace App\Service;

final class PriceCalculator
{
    public function withTax(float $price, float $rate = 0.18): float
    {
        return round($price * (1 + $rate), 2);
    }
}
src/Model/Product.php
PHP
<?php

declare(strict_types=1);

namespace App\Model;

use App\Service\PriceCalculator;

final class Product
{
    public function __construct(
        private string $name,
        private float $price,
        private PriceCalculator $calculator = new PriceCalculator(),
    ) {}

    public function label(): string
    {
        return $this->name . ": " . $this->calculator->withTax($this->price);
    }
}
index.php
PHP
<?php
require_once __DIR__ . "/src/Service/PriceCalculator.php";
require_once __DIR__ . "/src/Model/Product.php";

use App\Model\Product;

echo (new Product("Pen", 100))->label();
Output
OUTPUT
Pen: 118

Writing require_once for every class does not scale. The next lessons show how an autoloader does it automatically.

Common layers

FolderHolds
Model/ or Entity/Objects that represent your data (Product, User)
Repository/Classes that load and save models
Service/Business logic (PriceCalculator, OrderPlacer)
Http/ or Controller/Code that receives requests
Exception/Your custom exceptions
Support/ or Util/Small helpers

There is no single correct structure. Pick one, and keep it consistent.

Keep public/ thin

Only the public/ folder is reachable from the web. Put everything else (src/, vendor/, config) outside it. The public/index.php file loads the autoloader and starts the app. That way a server mistake cannot expose your code.

Name for the role

UserRepository, OrderService, InvalidEmailException. A reader can guess what each class does from its name and folder.

Do not nest too deeply

Two or three levels (App\Http\Controllers\Admin) is plenty. More than that makes names long and hard to import.

info
Why this matters in Laravel
A Laravel project follows this structure: app/Models, app/Http/Controllers, app/Services. The App\ namespace maps to the app/ folder with PSR-4. Once you know the rule, finding any class takes seconds.