Понимание MVC

В последние несколько дней я широко читал книги и веб-страницы об ООП и MVC в PHP, чтобы я мог стать лучшим программистом. Я столкнулся с небольшой проблемой в моем понимании MVC:

Где я могу разместить mysql_query ?

Должен ли я помещать его в контроллер и вызывать метод на модели, которая возвращает данные на основе предоставленного запроса? Или я должен положить его в саму модель? Являются ли оба варианта, которыми я предоставляю полный мусор?

Материалы по теме MVC

Вы могли бы перечислить книги, которые вы читали, потому что большинство (если не все) PHP-книг, которые касаются MVC, ошибочны.

Если вы хотите стать лучшим разработчиком, я бы рекомендовал вам начать с статьи Мартинга Фаулера – GUI Architectures . Далее следует книга от того же автора – «Шаблоны архитектуры корпоративных приложений» . Затем следующим шагом будет изучение принципов SOLID и понимание того, как писать код, который следует за Законом Деметры . Это должно охватывать основы =]

Могу ли я использовать MVC с PHP?

На самом деле, нет. По крайней мере, не классический MVC, как он был определен для Smalltalk .

Вместо этого в PHP у вас есть еще 4 шаблона, которые нацелены на одну и ту же цель: MVC Model2, MVP, MVVM и HMVC. Опять же, я слишком ленив, чтобы писать о различиях еще раз, поэтому я просто свяжусь со старым комментарием .

Что такое модель?

Первое, что вы должны понимать, это то, что модель в MVC не является классом или объектом. Это слой, который содержит множество классов. В основном слой модели – это все слои, объединенные (хотя второй слой должен называться «Object Object Layer», поскольку он содержит «Объекты модели домена»). Если вы хотите прочитать краткое резюме о том, что содержится в каждой части слоя модели, вы можете попробовать прочитать этот старый комментарий (перейдите к разделу «сторона примечания»).

Модельный слой состоит из всех трех концентрических кругов
Изображение взято из статьи Service Layer на сайте Фаулера.

Что делают контроллеры?

Контроллер имеет одну важную ответственность в MVC (я расскажу о реализации Model2 здесь):

Выполнять команды по структурам из уровня модели (сервисы или объекты домена), которые изменяют состояние указанных структур.

Обычно у него есть второстепенная ответственность: привязывать (или иначе передавать) структуры от уровня модели к представлению, но это становится сомнительной практикой, если вы следуете за SRP

Где я могу поместить код, связанный с SQL?

Хранение и извлечение информации обрабатывается на уровне источника данных и обычно реализуется как DataMapper (не путайте с ORM, которые злоупотребляют этим именем).

Вот как упростило бы его использование:

 $mapper = $this->mapperFactory->build(Model\Mappers\User::class); $user = $this->entityFactory->build(Model\Entities\User::class); $user->setId(42); $mapper->fetch($user); if ($user->isBanned() && $user->hasBannExpired()){ $user->setStatus(Model\Mappers\User::STATUS_ACTIVE); } $mapper->store($user); 

Как вы видите, ни в коем случае объект домена не знает, что информация из него была сохранена. И ни то, ни другое, о том, где вы помещаете данные. Он может храниться в MySQL или PostgreSQL или некоторой базе данных noSQL. Или, возможно, нажата на удаленный REST API. Или, может быть, картограф был манерой для тестирования. Все, что вам нужно будет сделать, чтобы заменить картограф, предоставляет этот метод на разных фабриках.

Также см. Эти связанные должности:

  • понимание MVC-просмотров в PHP
  • проверяемые контроллеры с зависимостями
  • как услуги должны взаимодействовать друг с другом?
  • MVC для продвинутых разработчиков PHP

Model и Entity Classes представляют данные и логику приложения, что многие называют бизнес-логикой. Обычно он несет ответственность за:

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

Вот диаграмма последовательности MVC, которая показывает поток во время HTTP-запроса:

введите описание изображения здесь

В этом случае модель – лучшее место для реализации кода, доступного для доступа к базе данных.

Модель содержит объекты домена или структуры данных, которые представляют состояние приложения. [википедия] . Таким образом, модель будет местом для вызова базы данных.

В «классическом» (отсутствие лучшего слова atm) шаблоне MVC представление получило бы текущее состояние из модели.

Не делайте ошибку, говоря, что модель предназначена для доступа к базе данных. Это больше, чем просто доступ к базе данных.

Во- mysql_query() , не используйте mysql_query() и family; они устарели, поэтому рассмотрите также изучение PDO и / или mysqli.

Модель заботится об обработке данных; он обеспечивает интерфейс к контроллеру, посредством которого он извлекает и / или сохраняет информацию. Таким образом, это будет основное место, где происходят действия с базой данных.

Обновить

Чтобы ответить на вопрос, заданный OP в комментариях: «одна общая модель для всего db или модель для каждой таблицы / действия?»

Модели предназначены для абстрагирования отдельных таблиц (хотя существуют модели, которые обрабатывают только одну таблицу); например, вместо того, чтобы запрашивать все статьи и затем запрашивать имена пользователей для авторов, у вас будет одна функция:

 function getArticles() { // query article table and join with user table to get username } 

Сколько моделей, которые вы создадите, в значительной степени зависит от того, насколько велик проект и как взаимосвязаны данные. Если вы можете идентифицировать независимые группы данных, вероятно, вы создадите модель для каждой группы; но это не сложно и быстро.

Манипуляции данными могут быть частью одной и той же модели, если вам не требуется четкое разделение между моделями только для чтения и только для записи (я бы не знал ситуации, которая оправдывает это, но кто знает).

Чтобы идти еще дальше, ваша модель не должна содержать код доступа к базе данных. Это относится к другому уровню за пределами Model / View / Controller: это называется уровнем persistence , который может быть реализован с использованием Object-Relational Mapper, такого как популярная Doctrine 2 для PHP.

Таким образом, вы никогда не трогаете какой-либо (мой) код SQL. Настойчивость слой заботится об этом за вас. Я действительно советую вам взглянуть на учебник Doctrine, это действительно профессиональный способ создания ваших приложений.

Вместо работы с необработанными данными, загруженными из базы данных, вы создаете объекты, которые содержат ваши данные, и поведение, связанное с ним.

Например, у вас может быть класс User , например:

 class User { protected $id; protected $name; protected $privileges; public function setName($name) { ... } public function getName() { ... } public function addPrivilege(Privilege $privilege) { ... } public function getPrivileges() { ... } } 

Контроллер будет взаимодействовать только с объектами:

 class UserController { public function testAction() { // ... $user = $em->getRepository('User')->find(123); // load User with id 123 $user->setName('John'); // work with your objects, echo $user->getName(); // and don't worry about the db! $em->flush(); // persist your changes } } 

За кулисами ORM берет на себя всю низкоуровневую работу по выдаче запроса SELECT , создавая экземпляр объекта, обнаруживая изменения в вашем объекте и выдавая необходимый оператор UPDATE !