PHP project layout – how to organise files so a small app does not turn into a single 2,000-line script named index.php with everything crammed inside.
The public folder pattern
The most important habit: only one folder should be web-accessible. Call it public/. Your web server document root points there. Everything else – config, classes, templates, vendor – lives outside it and cannot be fetched directly.
my-app/
├── public/
│ └── index.php # front controller (entry point)
├── src/
│ ├── Controllers/
│ ├── Models/
│ └── Services/
├── templates/
├── config/
│ └── app.php
├── storage/
│ └── logs/
├── vendor/ # Composer (later)
└── composer.json
Apache or nginx serves only public/. A request to /../../config/app.php should fail – because that path is not under the document root.
Separate concerns by folder
You do not need a framework’s folder names, but the idea is the same:
- Controllers – read the request, call services, pick a response
- Models – data access (database queries, save/load records)
- Services – business logic that does not belong in a controller
- templates/ – HTML views (plain PHP or Twig later)
- config/ – settings returned as PHP arrays
- storage/ – logs, uploads, cache files (not in git if generated)
A minimal public/index.php
Every request hits one file first. That file bootstraps the app and hands off to a router (we build one in a later tutorial). For now:
<?php
declare(strict_types=1);
require dirname(__DIR__) . '/vendor/autoload.php';
$config = require dirname(__DIR__) . '/config/app.php';
// Router and dispatch come later
echo 'App bootstrapped';
Naming and namespaces
Match folder names to PHP namespaces. A class AppControllersHomeController lives in src/Controllers/HomeController.php. Composer’s autoloader maps this for you – we set that up in the next tutorial.
What not to do
- Mix HTML, SQL, and validation in one file with no functions
- Store uploaded files next to PHP scripts in
public/ - Commit
.envor database passwords to git - Create a
includes/folder andrequiretwenty files by hand with no autoloader
Start simple. Two or three folders beat a perfect enterprise layout you never finish. You can refactor when the project grows – but keeping the document root tight is worth doing on day one.

