【问题标题】:PHP - How should the controller communicate data with the model layer in a proper MVC patternPHP - 控制器应如何以适当的 MVC 模式与模型层通信数据
【发布时间】:2014-05-05 12:13:10
【问题描述】:

我研究了很多次,向stackoverflow专家寻求最佳实践,但我仍然找不到解决方案,我可能已经得到了正确的答案,但我没有得到它。

我一直想创建一个“正确”的 MVC 模式来处理我的项目,例如我一直在研究这个 http://www.phpro.org/tutorials/Model-View-Controller-MVC.html 但我被告知这是一个糟糕的设计,我应该不再使用注册模式。

所以我查看了 teresko 的答案,尽管它很旧,但可以在这里看到 How should a model be structured in 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;
    }
}

这实际上很棒,但在我看来,从面向对象的角度来看,这是完全错误的,因为它不是面向对象友好的,因为 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 和工厂的想法好吗?控制器和模型层之间的正确通信方式是什么?

【问题讨论】:

    标签: php oop design-patterns model-view-controller factory


    【解决方案1】:

    并非如此,但是对于如何实现 MVC 没有任何规则,只要您明确定义了 M V C 并且 C 充当 M 和 V 的协调器。

    工厂的工厂显然超出了工程设计,如果您不需要它,请不要实施它。为了便于您应用 MVC,您需要了解 1) MVC 是 UI 层的一部分,2) 模型指的是其他层的位(例如,业务、持久性或应用程序/服务) 由 UI 使用。

    控制器总是直接与模型通信,但根据用例,模型意味着上面提到的层位。在“普通”应用程序中,通常是这样的:控制器使用应用程序服务(MVC 模型)来更新业务模型。服务应该被注入到控制器构造函数中。

    出于查询目的,控制器可以使用“查询服务”或仅查询存储库,这样它就不会包含持久性逻辑(如编写 sql)。还是和上面一样,只是这一次,Model 代表 Persistence bits。

    所以你看,Mvc 模型实际上是 UI 使用的其他层的外观,并且您希望控制器不能直接访问例如业务层,因为控制器实际上应该只是协调 要更改的模型以及要呈现的视图模型。相反,应用程序服务将使用业务/持久性对象来实现应用程序用例。

    一切都是为了尊重关注点分离单一职责原则

    【讨论】:

    • 那么当你说我需要给控制器注入应用服务时,应用服务会是什么样子呢?应该在哪里创建?它应该由服务工厂创建吗?
    • 忘掉工厂吧。应用程序服务由应用程序开发人员创建,并且特定于该应用程序。通常,MVC 框架应该使用 DI 容器来创建控制器,它负责注入部分。顺便说一句,有很多 Mvc 框架,至少学习其中一个,然后遇到一些限制后创建自己的框架。不要重新发明轮子,除非它是一个更好的轮子。
    • Not really, but there aren't any rules in how to implement MVC as long as you have M V C clearly defined and C acts as a coordinator for M and V. 这是不正确的。 because the controller should really just coordinate what model to change and what view model to be rendered. 完全错误..
    • @RonniSkansing 什么是正确?也随意提供一个代码示例,我想看看一个正确的控制器是如何实现的
    • @MikeSW 试试维基百科的文章。 Rails、CI、php 框架没有实现甚至接近 mvc scerio。对不起,你被误导了。看看stackoverflow.com/questions/3066590/… 就明白 mvc 不仅仅是 3 个独立的关注点和文件夹结构。
    猜你喜欢
    • 2012-01-22
    • 2011-01-15
    • 1970-01-01
    • 2019-06-21
    • 2015-01-19
    • 2013-11-29
    • 2011-02-24
    • 2013-06-26
    • 1970-01-01
    相关资源
    最近更新 更多