【问题标题】:PHP MVC Model Relations - MySQLPHP MVC 模型关系 - MySQL
【发布时间】:2017-06-28 15:06:35
【问题描述】:

我正在构建一个小而简单的 PHP 内容管理系统,并选择采用 MVC 设计模式。

我正在努力掌握我的模型应该如何与数据库结合使用。

我想将数据库查询本身分开,这样如果我们将来选择更改我们的数据库引擎,这样做很容易。

作为一个基本概念,下面提出的解决方案是否可行,是否有更好的方法来处理这种方法的缺陷是什么?

首先,我有一个数据库类来处理所有 MySQL 特定的代码:

class Database
{
    protected $table_name;
    protected $primary_key;

    private $db;

    public function __construct()
    {
        $this->db = DatabaseFactory::getFactory()->getConnection();
    }

    public function query($sql)
    {
        $query = $this->db->prepare($sql);
        $query->execute();
        return $query->fetchAll();
    }

    public function loadSingle($id)
    {
        $sql = "SELECT * FROM $this->table_name WHERE $this->primary_key = $id";
        return $this->query($sql);
    }

    public function loadAll()
    {
        $sql = "SELECT * FROM $this->table_name";
        return $this->query($sql);
    }
}

其次,我有一个模型,在这种情况下可以容纳我的所有菜单项:

class MenuItemModel
{
    public $menu_name;
    public $menu_url;       

    private $data;

    public function __construct($data)
    {
        $this->data = $data;
        $this->menu_name = $data['menu_name'];
        $this->menu_url = $data['menu_url'];
    }
}

最后,我将有一个“工厂”将两者结合在一起:

class MenuItemModelFactory extends Database
{
    public function __construct() {
        $this->table_name = 'menus';
        $this->primary_key = 'menu_id';
        parent::__construct();
    }

    public function loadById($id) 
    {
        $data = parent::loadSingle($this->table_name, $this->primary_key, $id);
        return new MenuItemModel($data);
    }

    public function loadAll()
    {
        $list = array();
        $data = parent::loadAll();
        foreach ($data as $row) {
            $list[] = new MenuItemModel($row);
        }
        return $list;
    }
}

【问题讨论】:

标签: php mysql model-view-controller


【解决方案1】:

您的解决方案当然可以,但存在一些缺陷。

  1. Database 类在其构造函数类DatabaseFactory 内部使用 - 这不好。 DatabaseFactory 必须自己创建 Database 对象。不过这里没问题,因为如果我们查看 Database 类,我们会发现它不是数据库,它是某种 QueryObject 模式(有关更多详细信息,请参阅 link)。所以我们可以通过将类Database重命名为更合适的名称来解决这里的问题。

  2. MenuItemModelFactory 类是 Database 类的扩展 - 这不好。因为我们已经决定,Database 只是一个查询对象。所以它必须只包含通用查询数据库的方法。在这里,您将创建模型的知识与一般数据库查询相结合。不要使用继承。只需在MenuItemModelFactory 中使用Database(查询对象)的实例来查询数据库。所以现在,如果您决定迁移到另一个数据库并更改 SQL 语法,您只能更改“数据库”的实例。并且 MenuItemModelFactory 类不会因为迁移到新的关系数据库而改变。

  3. MenuItemModelFactory 不适合命名,因为 DDD(域驱动设计)中的工厂目的是在需要许多参数或其他对象时隐藏创建实体或聚合的复杂性。但是在这里,您并没有隐藏创建对象的复杂性。您甚至没有“创建”对象,而是从某个集合“加载”对象。

所以如果我们考虑到所有的缺点并改正它们,我们就会得出这样的设计:

class Query
{
    protected $table_name;
    protected $primary_key;

    private $db;

    public function __construct()
    {
        $this->db = DatabaseFactory::getFactory()->getConnection();
    }

    public function query($sql)
    {
        $query = $this->db->prepare($sql);
        $query->execute();
        return $query->fetchAll();
    }

    public function loadSingle($id)
    {
        $sql = "SELECT * FROM $this->table_name WHERE $this->primary_key = $id";
        return $this->query($sql);
    }

    public function loadAll()
    {
        $sql = "SELECT * FROM $this->table_name";
        return $this->query($sql);
    }
} 

class MenuItemModel
{
    public $menu_name;
    public $menu_url;       

    private $data;

    public function __construct($data)
    {
        $this->data = $data;
        $this->menu_name = $data['menu_name'];
        $this->menu_url = $data['menu_url'];
    }
}

class MenuItemModelDataMapper
{
    public function __construct() {
        $this->table_name = 'menus';
        $this->primary_key = 'menu_id';
        $this->query = new Query();
    }

    public function loadById($id) 
    {
        $data = $this->query->loadSingle($this->table_name, $this->primary_key, $id);
        return new MenuItemModel($data);
    }

    public function loadAll()
    {
        $list = array();
        $data = $this->query->loadAll();
        foreach ($data as $row) {
            $list[] = new MenuItemModel($row);
        }
        return $list;
    }
}

还可以考虑阅读以下内容:

【讨论】:

    猜你喜欢
    • 2014-12-15
    • 1970-01-01
    • 1970-01-01
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-20
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多