微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

php – 单片模型

背景

这是一个漫长而复杂的问题.我使用PHP / MySQL作为例子(因为它是一个实际的例子),但这理论上可以应用于其他语言.忍受我.

没有ORM的MVC框架

我正在创建一个使用自己的框架的应用程序.由于各种原因,不接受以下对此问题的回答:

>为什么不使用X框架?
>为什么不使用X ORM?

这个应用程序执行自己的查询(由我编写),这就是我现在要保留的方式.

商业逻辑?

“商业逻辑”似乎是一个毫无意义的流行语,但我认为它本质上意味着

The queries and the logic that builds the result set based on those queries

我还读到MVC中的Model应该完成所有的业务逻辑.

User.PHP是884行

既然我已经让我的应用程序运行得相当好,我想重构它以便不会有这样的可憎之处. User.PHP本质上是用户的模型(显然).我在其中看到了一些我可以轻松采摘的责任,但我遇到的一个主要障碍是:

如何将SOLID与MVC协调?

User.PHP增长如此之大的原因是因为我做了任何需要该文件中的User成员的查询.用户用于大量操作(它需要做的不仅仅是CRUD),因此任何需要userid,username等的查询都由此文件中的函数运行.显然,查询应该在模型中(而不是控制器),但我觉得这绝对应该以某种方式分开.我需要完成以下任务:

>以分区方式创建一个涵盖所有这些必要查询的API
>在没有必要时,避免访问DB连接类
>将用户数据添加到视图中(User.PHP正在执行此操作 – 视图对象由setter注入,我认为这也很糟糕).

…所以我可以做的是创建其他对象,如UserBranchManager,UserSiteManager,UserTagManager等,每个对象都可以有相关的查询和注入的DB对象来运行这些查询,但是他们如何得到令人垂涎的用户: :$userid他们需要运行这些查询?不仅如此,我怎么能通过Branch :: $branchid?这些成员不应该是私人的吗?为他们添加一个吸气剂也使这一点毫无意义.

我也不确定在哪里绘制一个对象应该做多少的线.很多操作类似但仍然不同.每个人的课程将是一个巨大的矫枉过正.

可能的答案

如果我无法获得任何帮助,我将要做的(或至少尝试做的)是为上述对象(例如UserBranchManager)提供某种构建依赖关系的依赖注入容器,并将它们注入相关的控制器.这些将具有DB和Query对象.可以将Query对象传递给低级模型(如User)以根据需要绑定参数,更高级别的模型或它们被调用的任何内容都会将结果返回给控制器,控制器也会根据需要将数据添加到模板中. .我看到的一些可能的障碍是创建适当的合同(例如,UserController应该优选地取决于用户模型的一些抽象),但是不可避免地需要一些细节,特别是当涉及到视图时.

任何人都可以提供一些智慧来回应我的漫无边际的问题吗?

回复@tereško

他不仅在这里提供了很好的答案,而且在How should a model be structured in MVC?也提供了很好的答案

根据要求,这里有一些非常简化的代码(基本上是服务一个请求).一些重要的说明:

>现在,控制器不是类,只是文件

>控制器还处理很多路由

>没有“视图”对象,只有模板
>这可能看起来很糟糕

这些也是需要改进的地方,但我最担心的是模型(特别是用户,因为它失控了):

#usr.PHP -- controller
$route = route();
$user = '';
$branch = '<TRUNK>';
if (count($route) > 0) {
   if (count($route) > 1) {
      list($user, $branch) = $route;
   }
   else {
      list($user) = $route;
   }
}

$dec = new Decorator('user');
$dec->css('user');

if (isset($_SESSION['user']) && $_SESSION['user']->is($user)) {
   $usr = $_SESSION['user'];
}
else {
   $usr = new User(new DB, $user);
}
$usr->setUpTemplate($dec, $branch);
return $dec->execute();

# User.PHP -- model
class User {
   private $userid;
   private $username;
   private $db;

   public function __construct(DB $db, $username = null) {
      $this->username = $username;
      $this->db = $DB;
   }

   public function is($user) {
      return strtolower($this->username) === strtolower($user);
   }

   public function setUpTemplate(Decorator $dec, $branch) {
      $dec->_title = "$this->username $branch";
      // This function runs a moderately complicated query
      // joining the branch name and this user id/name
      $dec->branch = $this->getBranchdisplay($branch);
   }
}

关于答案的问题

在这里回答:

>您谈论的是不要使用缓存/身份验证/授权.这些重要吗?他们为什么不被覆盖?它们如何与模型/控制器/路由器相关?
> Data Mapper示例的Person类包含getExemption,isFlaggedForAudit等方法.那些是什么?看起来这些计算需要DB数据,那么它是如何获得的呢?人物映射器离开选择.不重要吗?
>什么是“域逻辑?”

回答5863870(特别是代码示例):

>这些工厂对象不应该是抽象的(并且不依赖于通过new创建)或者这些是特殊的吗?
>您的API如何包含必要的定义文件
>我已经阅读了很多关于如何在构造函数中注入依赖项的最佳方法(如果它们是必需的).我假设您以这种方式设置工厂,但为什么不是对象/映射器/服务本身?抽象怎么样?
>您是否担心代码重复(例如,大多数模型在其类定义中需要_object_factory成员)?如果是这样,你怎么能避免这种情况?
>你正在使用受保护的.为什么?

如果你能提供最好的代码示例,因为我更容易选择那样的东西.

我理解你的答案所说的理论,这对你有很大的帮助.我仍然感兴趣的(并且不完全确定)是确保以最佳方式处理此API中对象的依赖关系(最糟糕的是到处都是新的).

解决方法:

不要混淆SOLID(你可以在我的博客上得到一个很好的解释:http://crazycoders.net/2012/03/confoo-2012-make-your-project-solid/

在考虑围绕您正在尝试构建的应用程序的框架时,SOLID非常棒.数据本身的管理是另一回事.您无法将SOLID S的单一责任应用于依赖于其他业务模型(如用户,组和权限)的业务模型.

因此,在构建应用程序时,必须让一些SOLID运行. SOLID的优点是确保您的应用程序背后的框架很强大.

例如,如果你构建自己的框架和业务模型,你可能会有另一个基类MODEL用于DATABASEACCESS,只记得你的MODEL不应该知道如何获取数据,只知道它必须获取数据.

例如:

Good: 
    - MyApp_Models_User extends MyApp_Framework_Model
    - MyApp_Models_Group extends MyApp_Framework_Model
    - MyApp_Models_Permission extends MyApp_Framework_Model
    - MyApp_Framework_Model
    - MyApp_Framework_Provider
    - MyApp_Framework_MysqLiProvider extends MyApp_Framework_Provider

      In this good part, you create a model like this:
      $user = new MyApp_Models_User(new MyApp_Framework_MysqLiProvider(...));
      $user->load(1234);

这样,您将防止单一责任失败,您的提供程序用于从存在的众多提供程序之一加载数据,并且您的模型表示您提取的数据,它不知道如何读取或写入数据,这就是供应商的工作……

Bad way:
    - MyApp_Model_User
    - MyApp_Model_Group
    - MyApp_Model_Permission

      define('MyDB',   'localhost');
      define('MyUser', 'user');
      define('MyPass', 'pass');
      $user = new MyApp_Models_User(1234);

使用这种不好的方法首先要解决单一责任,模型代表了某些东西,并且还管理数据的输入/输出.此外,您通过声明您需要为模型定义常量以连接到数据库并且您完全抽象数据库方法来创建依赖项,如果您需要更改它们并拥有37个模型,那么您将需要完成大量工作…

现在,你可以,如果你想要工作的坏方法…我仍然这样做,我知道它,但有时,当你有糟糕的结构,并想要重构,你可以而且应该反对一个原则只是为了正确而缓慢地重构,然后,重构一点,最后得到一些SOLID和MVC.

请记住,SOLID不适用于所有内容,它只是一个指南,但它是非常好的指南.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐