jjzjj

php - MVC、模型和数据访问对象

coder 2024-04-17 原文

我有一个理论问题,希望有人能帮我弄清楚。

我目前正在使用 MVC 设计模式用 PHP 编写一个简单的 Web 应用程序。我已经看到并阅读了一些关于该主题的教程,但它们通常要么过于复杂,要么过于简单。

所以我现在拥有的是一个简单的 User 模型:

class User {

    private $username;
    private $group; //user, admin, etc

    // getters
}

我还有一个简单的 Database 类实现了这个类:

interface DatabaseInterface {

    public function connect();
    public function disconnect();
    public function prepare($sql = null);
    public function execute($params = array());
    public function rowCount();
    public function fetch();
}

我的问题是我应该如何将这个 Database 类与填充我的 User 类链接起来?

我目前拥有的是另一个名为 UserDAO 的类,它在其构造函数中传递了一个 Database 类的引用,并且它有一个名为 的函数ValidateUser() 然后使用上述接口(interface)方法根据数据库检查用户。

class UserDAO {

    private $database;

    public function __construct($database) {

        $this->database = $database;
    }

    public function validateUser($username, $password) {

        $this->database->prepare('SELECT * FROM users WHERE...');
        ....
        return true/false;
    }
}

现在我通过构造函数将一个 UserDAO 对象传递给 User 类,并且还在 ValidateUser() 类中添加了另一个方法 User 类,它基本上只是调用 UserDAO 类中的 ValidateUser() 方法。

新的 User 类:

class User {

    private $username;
    private $group; //user, admin, etc
    private $userDAO;

    public function __construct($userDAO) {

        $this->userDAO = $userDAO;
    }

    public function validateUser($username, $password) {

        if($this->userDAO->validateUser($username, $password)) {

            // set stuff that i need
            return true;
        }

        return false;
    }

    // getters
}

我觉得有些地方不对劲。谁能帮助我理解这个过程的正常流程?

此外,Database 类是否通常保持静态以便我可以使用类似Database::instance() 的方法来调用连接?现在我正在 PHP 页面的开头创建一个数据库对象并将其传递。

如果有任何不清楚的地方,请随时给我留言,我会尽快解决。

感谢您的阅读,对于帖子的长度感到抱歉。

最佳答案

这取决于您的解决方案的最新程度。

单例

“最老”的版本是到处调用静态连接。您可以通过使用单例 实现这一点:

class database {

    private $instance = NULL;

    private function __construct()

    public function getDb() {
        return $this->instance?: $this->instance = new database();
    }

}

注册表

第二种较新的解决方案是使用注册表: 您可以有一个由所有其他类扩展的基类,并提供调用方法,例如

$this->getRegistry()->getDb

通常,注册表会在脚本的开头填写,例如在 Bootstrap 中。 优点是您可以更好地对组件进行单元测试,因为没有静态部分,并且您可以为开发和生产环境定义不同的注册表...

依赖注入(inject)

依赖注入(inject)中的第三个,“最新”也是最好的方法。 通常你会有一些框架来为你做这件事。这个想法是,无论何时调用类的构造函数,框架都会注入(inject)所有依赖项(如数据库连接)。

这样您就可以轻松定义“用户需要 DB 和 Redis。商店需要 DB、Config 和 FTP”... 虽然这对于较小的项目来说是一项开销,但对于经过全面测试的大型项目来说却很有帮助。

如果您曾经升级到多个数据库(例如,一个主数据库和多个从数据库),DI 非常适合,因为您可以为代码的每个部分提供完成工作所需的数据库, 无需更改一行代码。

关于php - MVC、模型和数据访问对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16986499/

有关php - MVC、模型和数据访问对象的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  3. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  4. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  5. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  6. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  7. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  8. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  9. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  10. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

随机推荐