8

最近几天,我广泛阅读了关于 PHP 中的 OOP 和 MVC 的书籍和网页,以便我可以成为一个更好的程序员。我对 MVC 的理解遇到了一个小问题:

我在哪里放一个mysql_query

我应该把它放在控制器中并在模型上调用一个方法,该方法根据提供的查询返回数据吗?或者我应该把它放在模型本身?我提供的两个选项都是垃圾吗?

4

5 回答 5

15

关于 MVC 主题的材料

您可以列出您正在阅读的书籍,因为大多数(如果不是全部)涉及 MVC 的 php 书籍都是错误的。

如果您想成为一名更好的开发人员,我建议您从 Martining Fowler 的文章 - GUI Architectures开始。其次是同一作者的书- “企业应用程序架构的模式”。那么下一步就是让你研究SOLID 原理并了解如何编写遵循得墨忒耳法则的代码。这应该涵盖基础知识=]

我可以将 MVC 与 PHP 一起使用吗?

并不真地。至少不是为 Smalltalk 定义的经典 MVC 。

相反,在 PHP 中,您有 4 种其他模式旨在实现相同目标:MVC Model2、MVP、MVVM 和 HMVC。同样,我懒得再写一次差异,所以我将链接到我的旧评论

什么是模型?

您必须了解的第一件事是 MVC 中的 Model 不是类或对象。它是一个包含多个类的层。基本上模型层是所有层的组合(尽管第二层应该称为“域对象层”,因为它包含“域模型对象”)。如果您想阅读有关模型层每个部分中包含的内容的快速摘要,您可以尝试阅读这个旧评论(跳到“旁注”部分)。

                            模型层由所有 3 个同心圆组成
图片取自Fowler 网站上的服务层文章。

控制器做什么?

Controller 在 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。或者,映射器可能是用于测试的模拟。要替换映射器,您需要做的就是为这种方法提供不同的工厂。

另外,请参阅以下相关帖子:

于 2012-05-21T12:16:27.293 回答
8

模型和实体类代表应用程序的数据和逻辑,许多人称之为业务逻辑。通常,它负责:

  1. 存储、删除、更新应用程序数据。通常它包括数据库操作,但实现调用外部 Web 服务或 API 的相同操作一点也不稀奇。
  2. 封装应用程序逻辑。这是应该实现应用程序所有逻辑的层

这是 MVC 序列图,它显示了 http 请求期间的流程:

在此处输入图像描述

在这种情况下,模型是实现访问数据库的代码的最佳位置。

于 2012-05-20T17:38:17.450 回答
2

一方面,不要mysql_query()和家人一起使用;它们已被弃用,因此请考虑学习 PDO 和/或 mysqli。

该模型负责数据处理;它为控制器提供一个接口,通过该接口检索和/或存储信息。所以这将是数据库操作发生的主要地方。

更新

要回答 OP 在评论中提出的问题:“整个数据库的通用模型还是每个表/动作的模型?”

模型旨在抽象出单个表(尽管有些模型专门处理单个表);例如,与其询问所有文章然后查询作者的用户名,不如使用如下函数:

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

您将创建多少模型很大程度上取决于项目的规模以及数据的相互关联程度。如果您可以识别独立的数据组,您可能会为每个组创建一个模型;但这不是硬性规定。

数据操作可以是同一个模型的一部分,除非您想要明确区分只读模型和只写模型(我不知道有什么情况值得这样做,但谁知道)。

于 2012-05-20T17:23:19.213 回答
2

模型包含表示应用程序状态的域对象或数据结构。[维基百科]。所以模型将是进行数据库调用的地方。

在“经典”(没有更好的词 atm)MVC 模式中,视图将从模型中获取当前状态。

不要误以为模型是用于访问数据库的。它不仅仅是访问数据库。

于 2012-05-20T17:28:21.570 回答
1

更进一步,您的模型不应包含数据库访问代码。这属于模型/视图/控制器之外的另一层:这称为持久层,可以使用对象关系映射器(例如流行的 PHP学说 2 )来实现。

这样,您就永远不会接触任何(我的)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语句等所有低级工作!

于 2012-05-20T17:52:16.707 回答