Composer, Autoloading, and Project Structure

Composer is not only a package installer. It defines autoloading, scripts, platform requirements, and a repeatable dependency graph for the application.

A Practical composer.json

{
    "name": "example/customer-portal",
    "description": "Customer portal application",
    "type": "project",
    "require": {
        "php": "^8.4",
        "ext-json": "*",
        "ext-pdo": "*",
        "vlucas/phpdotenv": "^5.6"
    },
    "require-dev": {
        "phpunit/phpunit": "^11.0"
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    },
    "scripts": {
        "test": "phpunit",
        "lint": "php -l public/index.php"
    },
    "config": {
        "sort-packages": true
    }
}
Set the PHP constraint to the supported version range for the environment you actually deploy. The example is a project policy, not a statement that every host runs that version.

Install and Update Mean Different Things

CommandUse
composer installInstall the exact dependency versions recorded in composer.lock. Use this in deployment.
composer updateResolve new versions allowed by composer.json and rewrite the lock file. Use intentionally during maintenance.
composer auditCheck installed dependency versions against known security advisories.
composer dump-autoload -oGenerate an optimized autoloader for production.

Keep the Document Root Small

customer-portal/
├── app/
├── config/
├── migrations/
├── public/
│   ├── index.php
│   └── assets/
├── storage/
├── templates/
├── tests/
├── vendor/
├── .env
├── composer.json
└── composer.lock

Configure the virtual host document root as customer-portal/public. That prevents accidental access to .env, logs, source code, and dependencies.

Bootstrap Once

<?php
declare(strict_types=1);

use Dotenv\Dotenv;

require dirname(__DIR__) . '/vendor/autoload.php';

$dotenv = Dotenv::createImmutable(dirname(__DIR__));
$dotenv->safeLoad();

set_exception_handler(static function (Throwable $exception): void {
    error_log((string) $exception);
    http_response_code(500);
    echo 'The application encountered an error.';
});

Dependency Rules

  • Commit composer.json and composer.lock for applications.
  • Do not commit vendor/ unless the deployment environment genuinely requires it.
  • Review package ownership, maintenance, release history, and transitive dependencies before adoption.
  • Keep production dependencies separate from development tools.
  • Run security audits and tests before merging dependency updates.