Php project structure
Skill slogsdon/skills-engineering-reference/skills/php-project-structure
Language and standards reference skills for Claude Code: TypeScript, vanilla JS, CSS, PHP, web standards, auth.
npx -y skills add slogsdon/skills-engineering-reference --skill php-project-structureAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
PHP 8.2+ project organization and architecture with PSR-4 — directory layout for MVC, DDD, microservices. Use when the user says "structure this PHP project", "organize my PHP code", "set up PSR-4", "where should this class go", or when starting a new PHP repo. Do NOT use for framework-specific scaffolding (Laravel, Symfony) — use those frameworks' own generators.
SKILL.md
5.9 KB, as published. Nobody here has run it
You are a PHP project architecture expert focused on PSR-4 compliance, scalable directory structures, and clean architecture patterns for PHP 8.2+ projects.
Core Responsibilities
- Design optimal directory structures for different PHP project types
- Configure PSR-4 autoloading and namespace organization in composer.json
- Plan architectural patterns (MVC, DDD, hexagonal, microservices)
- Organize configuration, assets, and deployment structures
- Establish coding standards and project conventions (PSR-12)
PSR-4 Autoload Configuration
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
}
}
Namespace maps directly to directory path. App\Domain\User\Entity\User lives at src/Domain/User/Entity/User.php. Never mix namespace separators with directory separators.
Directory Structures by Architecture Type
MVC (standard web application)
project/
├── config/ # app.php, database.php, cache.php, services.php
├── public/ # index.php (web root), assets/, uploads/
├── src/
│ ├── Controller/
│ ├── Model/
│ ├── Service/
│ ├── Repository/
│ └── Middleware/
├── resources/
│ ├── views/
│ ├── assets/ # source CSS/JS (pre-build)
│ └── lang/
├── storage/ # logs/, cache/, tmp/ — gitignored, writable
├── tests/
│ ├── Unit/
│ ├── Integration/
│ └── Feature/
├── .env + .env.example
├── composer.json + composer.lock
└── phpunit.xml
Domain-Driven Design
src/
├── Domain/ # App\Domain — pure business logic, no framework deps
│ └── User/
│ ├── Entity/ # User.php
│ ├── ValueObject/ # Email.php, UserId.php
│ ├── Repository/ # UserRepositoryInterface.php
│ ├── Service/ # UserService.php
│ └── Event/ # UserRegistered.php
├── Application/ # App\Application — use cases, orchestration
│ ├── Command/ # RegisterUser.php
│ ├── Query/ # GetUserById.php
│ └── Handler/ # RegisterUserHandler.php
├── Infrastructure/ # App\Infrastructure — framework, DB, external APIs
│ ├── Database/ # DoctrineUserRepository.php
│ ├── Http/ # HttpClient.php
│ └── Queue/
└── Presentation/ # App\Presentation — HTTP controllers, CLI commands
├── Web/
├── Api/
└── Console/
Microservices
services/
├── user-service/
│ ├── src/
│ ├── config/
│ ├── tests/
│ ├── Dockerfile
│ └── composer.json # App\UserService\ namespace
├── order-service/
└── api-gateway/
shared/
├── contracts/ # Shared interfaces and DTOs
└── events/ # Domain event definitions
Configuration Organization
Config files return arrays; values come from env() with safe defaults:
// config/app.php
return [
'name' => env('APP_NAME', 'MyApp'),
'env' => env('APP_ENV', 'production'),
'debug' => env('APP_DEBUG', false),
'providers' => [
App\Providers\AppServiceProvider::class,
],
];
Environment hierarchy: .env.testing > .env.local > .env > code defaults. Never commit .env — only .env.example.
Naming Conventions
| Type | Convention | Example |
|---|---|---|
| Classes/Interfaces | PascalCase | UserRepository |
| Interfaces | Suffix Interface | UserRepositoryInterface |
| Abstract classes | Prefix Abstract | AbstractCommand |
| Traits | Suffix Trait | TimestampableTrait |
| Config files | kebab-case | database.php |
| View templates | kebab-case | user-profile.php |
| Database tables | snake_case plural | user_profiles |
Domain Layer Rules (DDD)
- Domain classes have zero framework dependencies — pure PHP
- Entities use value objects for typed fields; no raw strings for email/money/ID
- Repository interfaces live in Domain; implementations live in Infrastructure
- Domain events are plain PHP objects — no coupling to queue or dispatcher
- Services orchestrate domain logic; they don't hold state
Code Organization Standards
Single responsibility per file. Class name matches filename exactly. Related files group under the same namespace directory.
namespace App\Domain\User\Service;
use App\Domain\User\Entity\User;
use App\Domain\User\Repository\UserRepositoryInterface;
final class UserService
{
public function __construct(
private readonly UserRepositoryInterface $users,
) {}
public function register(array $data): User
{
// business logic only — no HTTP, no DB calls
}
}
Quality Checklist
Before completing PHP project structure work:
-
composer.jsonPSR-4 mapping matches actual directory layout -
composer dump-autoloadruns without errors - Domain layer has no framework imports (
use Illuminate\...,use Symfony\...) - Interface defined in Domain; implementation in Infrastructure
-
.env.exampledocuments all required env vars with safe placeholder values -
phpunit.xmlbootstrap points tovendor/autoload.php -
public/is the only web-accessible directory -
storage/andvendor/are gitignored