【问题标题】:Understanding application logic in MVC了解 MVC 中的应用程序逻辑
【发布时间】:2013-05-12 06:36:10
【问题描述】:

为了以简单的方式理解 MVC(我正在尝试制作自己的演示应用程序),我遵循了 Symfony2 的 Symfony2 versus Flat PHP 材料,在此过程中我改变了一些东西,试图“改进”添加一些 OOP 实践的代码,我创建了一个 DB 类并由此更改了他们的模型:

<?php
// model.php
function open_database_connection()
{
    $link = mysql_connect('localhost', 'myuser', 'mypassword');
    mysql_select_db('blog_db', $link);

    return $link;
}

function close_database_connection($link)
{
    mysql_close($link);
}

function get_all_posts()
{
    $link = open_database_connection();

    $result = mysql_query('SELECT id, title FROM post', $link);
    $posts = array();
    while ($row = mysql_fetch_assoc($result)) {
        $posts[] = $row;
    }
    close_database_connection($link);

    return $posts;
}

对此(请忽略西班牙语):

<?php
/**
 * @author Me
 * 
 */
/**
 * post.php: clase post, elemento de texto básico del blog
 */
class Post
{
    /**
     * titulo del post
     * @var string
     */
    private $title;

    /**
     * Constructor de la clase Post
     * @param string $title
     */
    function __construct($title)
    {
       $this->title = $title;
    }

    /**
     * Get para titulo del post.
     * @return string
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * Set para titulo del post.
     * @param  string $title
     * @return self
     */
    public function setTitle($title)
    {
        $this->title = $title;
        return $this;
    }

    public function getAllPosts()
    {
        //Ummm what?
    }
}

我的问题是,getAllPosts() 方法在我的模型 post.php 中的什么位置?我做错了什么?唯一想到的是将方法创建为静态的,但这没有任何意义,我知道不应该那样做......

在此先感谢各位,似乎理解整个 MVC,Web 开发中类似 MVC 的结构给我带来了一些麻烦,呵呵...

注意:这与 Symfony 完全无关,我只是想遵循他们简单的类似 MVC 的实现(包括他们创建视图的方式(这显然不是应该实现 MVC 的“纯”方式) ))。

【问题讨论】:

  • 应用逻辑是模型的一个方面,它处理领域实体和存储抽象之间的交互。它通常包含在services中。

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


【解决方案1】:

你必须制作两个对象。

  • 实体对象 - 您创建的对象,代表数据库中的帖子。
    • getTitle()
    • setTitle(title)
  • 数据访问对象 - 管理数据库中的 Post 实体的类 (createPost)。
    • getAllPosts()
    • 保存帖子(帖子)

【讨论】:

  • 感谢您的回答,现在这个数据访问对象能给我举个例子吗?我将如何从说..我的控制器访问这些方法?与教程中使用的控制器一样。
  • 您是说这些与数据库交互的方法应该放在不同的类中,那么这些方法是静态的吗?
  • 一般避免使用静态方法。虽然它们有其用途,但很容易陷入将所有内容都变为静态并将代码转换为假 OOP 的陷阱,即包装在类中的过程代码。
  • 我正在使用 CodeIgniter 开发 PHP 应用程序。看看this question,它可能会给你一些帮助。也尝试阅读 CodeIgniter 文档的前言。很好地描述了 MVC 架构。用他们的话说,“模型”是数据访问对象,它与实体对象一起操作,他们在问题中说“自​​定义对象”。
【解决方案2】:

您只需要记住 MVC 是一种架构模式,它将业务层(模型)、UI(视图)、协调器(控制器)分开。请注意Model is polymoprhic,即它不仅仅是数据库。

MVC 本身就是关注点分离 (SoC) 原则的实现。 flat php 所做的(或实际上的任何语言)称为Transaction Script,它仅适用于简单的(脚本)任务。

如果您想要一个应用程序,一个提供许多(复杂)功能的虚拟产品,并且要求会随着时间而变化,您需要一个合适的架构来帮助您在不破坏其他内容的情况下进行修改。

在您的代码中,getAllPosts 方法违反了关注点分离以及单一责任原则 (SRP),因为 Post 除了建模 Post 还具有处理持久性的任务。

MVC 说要分离 Model 和 View 并使用 Controller 来协调这两者。这也意味着控制器应该只做管理工作,即选择模型和选择视图(或其他结果)。除非它是一个琐碎的家庭作业原型应用程序,否则不要将数据访问权限放入 Controller。让你的控制器只做他们需要做的事情。如果你的控制器有超过 10 行的代码,很可能是它做的太多了。

MVC 是一种非常简单的模式,要遵守纪律来尊重它要困难得多。

【讨论】:

  • 模型不是“多态的”。模型是一层。类可以是多态的,而不是层。
  • 模型是多态的,因为它可能意味着不同的东西(多态=多种形式)。它与 OOP 多态性无关。模型可以是一个层,但这个概念不仅仅用作一个层。我可以告诉你,很多使用 asp.net mvc 的开发人员将 View Model 误认为是 MVC 模型,这取决于应用程序可能相同也可能不同。模型飞来飞去对于了解它的多重含义非常有用。几乎网络上的每个人都默认使用 MVC。
  • 您似乎认为,MVC 代表“我的代码”。话又说回来,您似乎也认为 MVC 是一种“非常简单的模式”,这可以解释它。
  • MVC 是一个非常简单的模式,但是当人们谈论 Model 时,每个人都理解其他的东西。例如,您将其理解为既不是 Controller 也不是 View 的层,而其他人将其理解为数据库的别名。而且由于每个人都默认使用 MVC,因此了解我们所说的 M 非常重要。顺便说一句,视图模型是视图层还是模型层的一部分?
  • "ViewModel" 是 MVVM 设计模式的概念,被 ASP.NET MVC 扼杀。在 MVC 中有“presentation models”(我实际上更喜欢名称“演示对象”)。它们应该在视图中使用。另外,请阅读 thisthis
【解决方案3】:

您只实现了 MVC 结构的“M”(模型)部分。涉及多个实体的功能最好留给获取浏览器请求的控制器。所以你可以继续添加这样的类(使用优秀的Doctrine DBAL 访问层):

class PostController {
  private $myDb;

  public function __construct(Doctrine\DBAL\Connection $db) {
    $this->myDb = $db;
  }

  public function get() {
    if (!isset($_REQUEST['id'])) {
      $allPosts = $this->myDb->fetchAll('SELECT * FROM Post');
    }
    // pass $allPosts to the view layer...
  }
}

由于 Doctrine 指南明确警告要向控制器添加业务逻辑:在我个人看来,像获取所有记录这样的简单代码可以很好地进入控制器。然后,您可以使用接受列值数组的Post 构造函数将数据包装在模型实例中。然后,所有逻辑都可以按照建议使用您的实体。

如果您的数据库访问代码变得更加复杂,并且您发现自己不断地复制相同的代码 sn-ps,您可以从 StaNov 的构建单独数据访问层的建议开始。在那之前,我真的推荐

  1. 坚持使用库来进行低级数据库访问
  2. 使用完成工作的最简单的代码。复杂性很快就会困扰您。

【讨论】:

  • 谢谢你的回答,我明白了,只是我读到的每个人都对他们所谓的“瘦控制器,胖模型”保持立场,我认为这种逻辑会实现这就是为什么我对 StaNov 的观点感到好奇的原因。
  • 根本没有数据库/数据存储/持久性代码进入控制器。从数据库中获取所有帖子是模型的重要部分,而不是控制器。 MVC 用于保持应用程序的模块化和可扩展性; V 和 C 部分旨在与替代版本可互换。 IE。你有一个 HTTP 控制器和视图、一个 CLI 控制器和视图等,它们都与同一个模型进行交互。一旦你理解了这一点,很明显你不希望任何控制器中有任何数据库特定的逻辑。
  • 想一想,在这种情况下,我可能将控制器用作廉价的数据访问层。我的主要目标是将数据库访问权排除在模型之外,因为这是我放置所有真实逻辑的地方,我讨厌被 DBAL 代码弄乱。
猜你喜欢
  • 2013-03-09
  • 2011-11-03
  • 1970-01-01
  • 2010-12-29
  • 2015-11-10
  • 1970-01-01
  • 2011-02-25
  • 2013-04-12
  • 2013-11-15
相关资源
最近更新 更多