PHP - Как контроллер должен передавать данные со слоем модели в правильном паттерне MVC
Я много раз проводил исследования, спрашивая экспертов по stackru для лучшей практики, но я все еще не мог найти решение, мне, возможно, сказали правильный ответ, но я не получил его.
Я всегда хотел создать "правильный" шаблон MVC для работы над моими проектами, например, я изучал этот http://www.phpro.org/tutorials/Model-View-Controller-MVC.html но мне сказали, что это ужасный дизайн, и я не должен больше использовать шаблон регистрации.
Поэтому я посмотрел на ответ Тереско, хотя он очень старый, его можно увидеть здесь. Как должна быть структурирована модель в MVC? и у меня появилась идея использовать глобальную фабрику, которая будет создавать другие фабрики
Идея, которую я получил оттуда, заключается в том, чтобы создать большую фабрику под названием ServiceFactory
который будет создавать экземпляры других фабрик, таких как ModelFactory, которые будут создавать экземпляры классов, которые обслуживают слой модели, и ViewFactory, который будет обслуживать представление (в данный момент я думаю, что это довольно бесполезно).
Но получил что-то вроде этого:
namespace library\application;
use library\application\exceptions\ClassNotFoundException;
use library\application\exceptions\PackageNotFoundException;
class ServiceFactory {
private $mapper;
private $package;
private $services = array();
public function __construct(DataMapper $mapper) {
$this->mapper = $mapper;
}
/**
* Setting a default package
* @param $package string Package path
* @throws exceptions\PackageNotFoundException
*/
public function setDefaultPackage($package) {
if (is_dir('library' . $package)) {
$this->package = 'library' . $package;
return;
}
throw new PackageNotFoundException("The package: " . $package . " was not found.");
}
/**
* @param $name string Class name
* @param null $constructor IF the class needs constructor parameters, use it.
* @return Factory
* @throws exceptions\ClassNotFoundException
*/
public function create($name, $constructor = null) {
$path = $this->package . "\\" . $name;
if (file_exists($path)) {
if ($constructor) {
return new $path($constructor);
}
return new $path;
}
throw new ClassNotFoundException("The requested class was not found: " . $path);
}
/**
* @param $name string Class name
* @param $object object Object to register
*/
public function register($name, $object) {
$this->services[$name] = $object;
}
/**
* @param $name string Class name
* @return Factory
*/
public function get($name) {
if (isset($this->services[$name])) {
return $this->services[$name];
}
return null;
}
}
Это на самом деле удивительно, но, на мой взгляд, с точки зрения OO, это совершенно неправильно, потому что это не дружественно к объектно-ориентированному объекту, так как возвращаемый объект S ServiceFactory::create()
является анонимным, хорошо, это больше не анонимно, потому что цель класса - создавать экземпляры фабрик, конечно, просто добавили интерфейс фабрик взамен.
Но теперь следующая проблема, когда я хочу использовать фабрики для создания объектов, которые не должны иметь одинаковый интерфейс, вызовет проблемы в моей IDE, так как она не знает, какой объект я собираюсь вернуть, она может быть Foo, может быть Car и однажды это может быть HelloWorld.
Поэтому мне всегда придется объявлять переменную с объектом при использовании его в контроллере:
/**
* @var $items Items
* @var $categories CategoryModel
*/
$items = parent::getModelFactory()->create('Items');
$items->setDb(parent::getDatabase());
$categories = parent::getModelFactory()->create('Categories');
$categories->setDb(parent::getDatabase());
Сейчас в одном из Teresko
В ответе говорится следующее правило: A controller can not create instances of the Model layer
Итак, я предполагаю, что он имеет в виду как $foo = new Foo(); $foo->method($db);
в контроллере, но почему бы и нет? как контроллер на самом деле должен сообщать уровень модели?
Основная цель, которую я создаю для этого фабричного класса, состоит в том, чтобы new Object()
в классе контроллера, но поскольку он вызывает фабрику, которая создает экземпляр, он все еще рассматривается, поскольку я создаю экземпляр уровня модели в контроллере (я думаю).
Я также мог кэшировать объекты, используя ServiceFactory::register()
метод, но это не меняет ситуацию.
Так это ServiceFactory
а заводская идея в порядке? Как правильно взаимодействовать между контроллером и уровнем модели?
1 ответ
Не совсем, но нет никаких правил относительно того, как реализовать MVC, если вы четко определили MVC и C действует в качестве координатора для M и V.
Фабрика фабрик явно над инжинирингом, если она вам не нужна, не используйте ее. Чтобы вам было легко применять MVC, вам необходимо понять, что 1) MVC является частью уровня пользовательского интерфейса и 2) Модель относится к битам других уровней (например, Business, Persistence или Application/Service).) которые используются пользовательским интерфейсом.
Контроллер всегда связывается напрямую с моделью, но в зависимости от варианта использования модель означает, что биты слоев упомянуты выше. В "нормальном" приложении это обычно выглядит так: контроллер использует службу приложения (модель MVC) для обновления бизнес-модели. Служба должна быть внедрена в конструктор контроллера.
В целях запроса контроллер может использовать "службу запросов" или репозиторий только для запросов, чтобы он не содержал логику постоянства (например, написание sql). Это все тот же подход, что и выше, только на этот раз Модель представляет биты постоянства.
Итак, вы видите, что модель Mvc на самом деле является фасадом для других слоев, используемых пользовательским интерфейсом, и вы хотите, чтобы контроллер не имел прямого доступа к бизнес-уровню, например, потому что контроллер должен просто координировать, какую модель изменить и какую модель представления изменить. быть оказанным. В отличие от этого, сервис приложения будет реализовывать вариант использования приложения, используя объекты бизнес / постоянство.
Все на самом деле об уважении разделения интересов и принципа единой ответственности