Я бы воспринял этот вопрос скорее как подлинный запрос, чем как запрос на просмотр какой-либо статьи о SEO-спаме из Интернета. Так и идет:
Прежде всего, вам нужно понять, что термин «модель» неоднозначен. Он может представлять либо бизнес-логику всего приложения , либо просто то, что вы имели в виду - некоторый фрагмент кода, взаимодействующий с базой данных. Чтобы избежать этой двусмысленности, давайте придерживаться первого. Это поможет вам рассчитаться с контроллером. Тогда как мы будем называть «меньшую модель» хранилищем . Термин покрытия для кода, который фактически взаимодействует с базой данных.
У меня очень краткая рецензия, MVC в более простых терминах или структура современного веб-приложения . Это поможет вам обернуть голову вокруг MVC в целом.
Теперь ближе к вашему вопросу.
Оболочка базы данных не может рассматриваться как модель, в любом смысле. Оболочка базы данных - это служба , используемая классом хранения. Таким образом, в вашем приложении может быть как минимум 3 слоя:
- контроллер. Просто интерфейс для передачи запроса HTTP-клиента в бизнес-модель
- услуга или помощник. код, который обычно (и неправильно) написан в контроллере. Например, если вам нужно зарегистрировать пользователя, в контроллере вы вызываете метод из пользовательской службы, предоставляя данные, полученные от клиента.
- класс хранения. Фактический код для взаимодействия с базой данных. Например, это может быть класс User, который содержит такие методы, как register и тому подобное. Этот класс будет использовать PDO (или более продвинутую оболочку, или экземпляр ORM) в качестве переменной класса.
Где последние два должны фактически инкапсулировать бизнес-логику всего вашего приложения.
Самая сложная часть здесь - создание экземпляра класса Storage. Поскольку соединение должно быть выполнено только один раз, должны существовать средства для создания экземпляра объекта UserStorage, обеспечивающего ему соединение с базой данных. Это немного другая проблема, которая решается с помощью контейнера для инъекций зависимости
Для иллюстрации выше с небольшим количеством кода
class UserController extends Controller
{
public function create($request)
{
$userService = $this->serviceContainer->get('user_service');
$userService->create(
$request->email;
$request->password;
);
}
}
class UserService
{
public function create($username, $password)
{
// here, userStorage instance was already injected
// in the UserService in the controller by DI container
$this->userStorage->create(
$request->email;
$request->password;
);
}
}
class UserStorage
{
public function create($username, $password)
{
$sql = "INSERT INTO user VALUES (null, ?, ?)";
// here, db instance was already injected
// in the UserStorage in the controller by DI container
$this->db->prepare($sql)->execute([$username, $password]);
}
}
Со всеми этими кажущимися повторениями это можно считать излишне многословным, но есть причины для этого:
- в реальном коде есть другие части на каждом этапе, например,
- Контроллер будет проверять отправленную форму (например, была ли форма фактически отправлена, равны ли пароли и т. Д.) И вызывать View для визуализации формы.
- UserService может выполнить дополнительные проверки, например, существует ли такая электронная почта
- Различные пункты вызова
- UserService может вызываться из разных мест: из вышеприведенного контроллера, утилиты командной строки или контроллера REST.
- UserStorage можно вызывать из еще большего количества мест. Например, существует TaskService, в котором перечислены задачи, принадлежащие пользователям, и он, естественно, будет эффективно использовать класс UserStorage. И так далее.
Так что имеет смысл разделить ваши слои таким образом.
Конечно, это просто упрощенная черновая модель, она не реализует ORM, который обычно здесь, и многие другие. Но чем проще эскиз, тем меньше деталей, тем проще понять основную идею.