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 на самом деле является фасадом для других слоев, используемых пользовательским интерфейсом, и вы хотите, чтобы контроллер не имел прямого доступа к бизнес-уровню, например, потому что контроллер должен просто координировать, какую модель изменить и какую модель представления изменить. быть оказанным. В отличие от этого, сервис приложения будет реализовывать вариант использования приложения, используя объекты бизнес / постоянство.

Все на самом деле об уважении разделения интересов и принципа единой ответственности

Другие вопросы по тегам