Бортовой журнал Ктулху

Правильная организация кода в PHP фреймворке

Обычно, фреймворк состоит из контроллеров, моделей и представлений. И рассмотрим типичную его структуру, пройдемся по основным его составляющим и разберем, что в них должно быть, а чего не должно быть.

Контроллеры

Контроллер в PHP фреймворке выполняет обработку запросов. Вот основные принципы, что он должен и чего не должен содержать:

Что должен содержать контроллер:

1. Логика обработки запросов:

* Получение данных из запроса (GET, POST, PUT, DELETE).

* Валидация входящих данных.

2. Взаимодействие с моделями:

* Обращение к моделям для получения, создания, обновления или удаления данных.

3. Подготовка данных для представлений (Views):

* Подготовка данных, которые будут отображены пользователю.

* Определение, какое представление (View) будет использоваться.

4. Вызов представлений:

* Передача данных в представления.

* Рендеринг представлений.

5. Редиректы и ответы:

* Выполнение редиректов при необходимости.

* Формирование ответов в различных форматах (HTML, JSON, XML и т.д.).

Чего не должен содержать контроллер:

1. Сложную бизнес-логику:

* Бизнес-логика должна быть вынесена в модели или сервисы. Контроллер должен быть "тонким" и просто вызывать нужные методы.

2. Длительные операции и обработка данных:

* Эти задачи должны выполняться в моделях или сервисах, чтобы контроллер оставался быстрым и отзывчивым.

3. Логика представлений:

* Контроллер не должен содержать HTML-код или логику, связанную с представлением данных. Это задача представлений (Views).

4. Дублирующийся код:

* Избегайте дублирования кода в разных методах контроллера. Вынесите повторяющиеся части в отдельные методы или сервисы.

5. Доступ напрямую к базе данных:

* Вся работа с базой данных должна идти через модели или репозитории, а не напрямую из контроллера.

Модели

В модели PHP фреймворка должны быть:

1. Атрибуты (свойства) модели: Поля, соответствующие колонкам базы данных, а также вычисляемые или виртуальные атрибуты, которые являются производными от других данных.


2. Методы для работы с данными:

* Методы для получения данных: Например, find(), findOne(), all().

* Методы для сохранения и обновления данных: Например, save(), update().

* Методы для валидации: Например, rules(), которые задают правила валидации данных.

* Методы для работы с отношениями: Например, hasOne(), hasMany() для определения связей с другими моделями.

3. Методы для обработки данных: Например, обработка данных перед сохранением (например, beforeSave(), afterSave()), вычисления, преобразования.


Чего не должно быть в модели:

1. Бизнес-логика: Модели не должны содержать сложные бизнес-правила или логику, связанную с поведением приложения. Это следует вынести в отдельные сервисы или контроллеры.


2. Логика отображения: Модель не должна включать методы или данные, связанные с представлением (например, HTML-разметку, логику формирования шаблонов и т.д.). Это должно находиться в представлениях или контроллерах.


3. Сложные запросы к базе данных: Для сложных запросов лучше использовать репозитории или отдельные сервисы, чтобы модель оставалась простой и легко читаемой.


4. Логика маршрутизации: Модели не должны управлять маршрутами или отвечать за перенаправления, это задача контроллеров и роутеров.

Контроллеры для API и html страниц желательно делать отдельно.

Представление

В идеале, не должна содержать обращений в БД, преобразований данных, каких-то вычислений с данными. Только верстка и получение данных для наполнения страниц. Также, сюда подключаются js/css, специфичные для текущей страницы. Какие-то общие должны подключаться в layouts.


Компоненты/сервисы/репозитории

А тут создаем необходимые классы, относящиеся к проектам, страницам и т.д., где производим все действия над данными после получения из БД и до вывода в представление.

Это обеспечит разделение кода на слои, где каждый слой ответственный за свою часть работы.

В сервисах PHP фреймворка должны быть:

1. Бизнес-логика: Сервисы должны содержать основную бизнес-логику приложения. Это могут быть процессы, которые включают взаимодействие с моделями, внешними API, выполнение сложных расчетов и принятие решений.


2. Работа с несколькими моделями: Если логика требует взаимодействия с несколькими моделями или репозиториями данных, это лучше всего разместить в сервисе, а не в контроллере или модели.


3. Обработка и трансформация данных: Любая логика, связанная с обработкой или преобразованием данных перед их сохранением в базу данных или отправкой в представление, должна находиться в сервисах.


4. Работа с внешними сервисами или API: Интеграция с внешними API, отправка HTTP-запросов, работа с очередями сообщений или любыми другими внешними ресурсами также должна быть реализована в сервисах.


5. Работа с событиями и уведомлениями: Если в вашем приложении используются события (event-driven architecture), их обработка и логика реагирования могут быть реализованы в сервисах.


Чего не должно быть в сервисах:

1. Логика отображения: Сервисы не должны генерировать HTML, JSON или любые другие форматы для вывода. Это задача представлений или контроллеров.


2. Прямое взаимодействие с базой данных: Сервисы не должны напрямую обращаться к базе данных через SQL-запросы. Вместо этого они должны использовать модели или репозитории для работы с данными.


3. Маршрутизация и перенаправления: Логика маршрутизации и перенаправления должна находиться в контроллерах, а не в сервисах.


4. Избыточная логика: Сервисы не должны быть перегружены логикой, которая не связана напрямую с их задачей. Например, валидацию данных лучше вынести в модели или отдельные валидаторы.


5. Работа с сессиями или куками: Управление сессиями и куками должно осуществляться в контроллерах или middleware, но не в сервисах.