Комментарии (1)
🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Структура PHP-проекта: современный подход
Структура PHP-проекта определяет его масштабируемость, тестируемость и поддерживаемость. В отличие устаревших подходов с единой папкой src, современные проекты следуют принципам чистой архитектуры и Domain-Driven Design (DDD). Я рекомендую следующую структуру для enterprise-приложений:
1. Ключевые директории проекта
project/
├── app/
│ ├── Domain/ # Ядро бизнес-логики
│ ├── Application/ # Слой применения бизнес-правил
│ ├── Infrastructure/ # Реализации внешних зависимостей
│ └── Presentation/ # Контроллеры, API endpoints
├── config/ # Конфигурации, параметры окружения
├── public/ # Публичные файлы, index.php
├── tests/ # Unit, Integration, Functional тесты
├── resources/ # Шаблоны, переводы, assets
├── storage/ # Генерируемые файлы (лог, cache)
├── vendor/ # Composer зависимости
├── docker/ # Docker конфигурации
└── database/ # Migrations, seeds
2. Детализация слоев архитектуры
Domain Layer (Ядро бизнес-логики)
// app/Domain/User/Entities/User.php
namespace App\Domain\User\Entities;
class User {
private string $id;
private string $email;
public function changeEmail(string $email): void {
// Бизнес-правила валидации email
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new InvalidEmailException();
}
$this->email = $email;
}
}
- Entities: Основные бизнес-объекты с уникальной идентификацией
- Value Objects: Объекты без идентификатора (Email, Money)
- Aggregates: Группы связанных Entities
- Repositories Interfaces: Абстракции для доступа к данным
- Domain Events: События бизнес-процессов
Application Layer (Координация бизнес-процессов)
// app/Application/User/Commands/ChangeEmailCommand.php
namespace App\Application\User\Commands;
class ChangeEmailCommandHandler {
public function __construct(
private UserRepositoryInterface $repository
) {}
public function handle(ChangeEmailCommand $command): void {
$user = $this->repository->find($command->userId);
$user->changeEmail($command->newEmail);
$this->repository->save($user);
}
}
- Commands/CQRS: Команды для изменения состояния
- Queries: Запросы для чтения данных
- DTOs: Data Transfer Objects для передачи данных между слоями
- Services: Координация нескольких Domain объектов
Infrastructure Layer (Внешние реализации)
// app/Infrastructure/Persistence/Doctrine/UserRepository.php
namespace App\Infrastructure\Persistence\Doctrine;
class UserRepository implements UserRepositoryInterface {
public function find(string $id): User {
// Doctrine, Eloquent или другой ORM
return $this->entityManager->find(User::class, $id);
}
}
- Persistence: Реализации Repository (Doctrine, Eloquent)
- External Services: Клиенты API, интеграции
- Messaging: Реализации событий (RabbitMQ, Kafka)
- File Storage: Адаптеры для S3, локального хранилища
3. Критические принципы организации
- Инверсия зависимостей: Слои Domain и Application НЕ зависят от Infrastructure
- Следование SOLID: Каждый класс имеет одну ответственность
- Тестируемость: Domain и Application слои тестируются без внешних зависимостей
- Модульность: Группировка по бизнес-контекстам (User, Order, Payment)
4. Практические рекомендации
- Используйте Composer для управления зависимостями и автозагрузки (PSR-4)
- Разделите конфигурации по окружениям (local, production, testing)
- Применяйте миграции базы данных для контроля схемы данных
- Следуйте PSR стандартам для кодирования, автозагрузки, логгирования
- Используйте Docker для унификации окружения разработки
5. Пример реальной структуры с маршрутизацией
// public/index.php - единая точка входа
require __DIR__ . '/../vendor/autoload.php';
$container = require __DIR__ . '/../config/container.php';
$router = require __DIR__ . '/../config/routes.php';
$request = Laminas\Diactoros\ServerRequestFactory::fromGlobals();
$response = $router->dispatch($request, $container);
Такая структура позволяет:
- Изолировать бизнес-логику от фреймворков и инфраструктуры
- Легко заменять реализации (ORM, кеш, файловое хранилище)
- Эффективно тестировать каждый компонент отдельно
- Адаптироваться к изменениям требований бизнеса
- Сокращать coupling между модулями системы
Выбор структуры зависит от размера проекта: для небольших приложений можно использовать simplified MVC, но для enterprise-систем чистая архитектура становится обязательной.