agentsclimarketplace

Php project structure

Skill slogsdon/skills-engineering-reference/skills/php-project-structure

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.From its SKILL.md

Install
npx -y skills add slogsdon/skills-engineering-reference --skill php-project-structure

Assembled 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.

SKILL.md

5.9 KB, ~1.3k tokens by cl100k_base, 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

TypeConventionExample
Classes/InterfacesPascalCaseUserRepository
InterfacesSuffix InterfaceUserRepositoryInterface
Abstract classesPrefix AbstractAbstractCommand
TraitsSuffix TraitTimestampableTrait
Config fileskebab-casedatabase.php
View templateskebab-caseuser-profile.php
Database tablessnake_case pluraluser_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.json PSR-4 mapping matches actual directory layout
  • composer dump-autoload runs without errors
  • Domain layer has no framework imports (use Illuminate\..., use Symfony\...)
  • Interface defined in Domain; implementation in Infrastructure
  • .env.example documents all required env vars with safe placeholder values
  • phpunit.xml bootstrap points to vendor/autoload.php
  • public/ is the only web-accessible directory
  • storage/ and vendor/ are gitignored

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.