php - 手动滚动 ORM 类——单例、静态父类?

标签 php oop

我正在为我公司购买的数据仓库编写一个网络报告扩展。数据仓库是数据模型中立的,并且具有存储表关系和字段的元层数据的表。这使得我可以很容易地编写一个基本的 ORM 类,这正是我正在尝试做的。这一切都有效,但是...

我的 ORM 类保存 PDO 实例、表的字段(用作白名单)以及字段的元层信息。它还具有用于映射表关系(生成 FROM/JOIN 子句)和映射从 Web 提供的过滤器(生成 WHERE 子句)的便利函数。

SELECT 子句是根据请求的模型在 ORM 的子类中生成的。当页面加载时,需要构建多个模型。显然,我只需要一个 ORM 实例(如单态),但我希望每个子类都继承 ORM 的属性和便利函数——而无需在每次实例化子类时重做父类的查询。

单例模式可能适合这里,但我发现很难对单例进行子类化。我似乎无法让静态属性正常工作。

我想我已经很接近了,但我要么错过了一些东西,要么让这件事变得太困难了。我现在正在考虑将属性放入一个瘦类中并从那里扩展,同时将便利函数与特征混合在一起。我见过这个主题的类似问题,但还没有提出明确的解决方案。

我不在工作,但这是一个简化的代码示例,应该可以让您了解我正在尝试做的事情的要点。

Class ORM {

    protected $conn;
    protected $fields;
    protected $relations;
    protected $table;
    protected $sql;

    public function __construct ($view, $database) {

        $this->conn = new PDO(...$database...);
        $this->table = $view;
        $this->getFields();
        $this->getRelations();
    }

    private function getFields () {
        //select fields from metalayer where table = $table;
        //$this->fields = $result;
    }

    private function getRelations () {
        //select relations from relations where table = $table;
        //$this->relations = $result;
    }

    protected function mapTables ($tables) {
        // $this->sql = "FROM $this->table";
        // foreach ($tables as $table) {
        //    $this->sql .= "LEFT JOIN $table ON $relations[$table]['key1'] =  $relations[$table]['key2'];
    }

    protected function mapFilters ($filters) {
        // $this->sql = "WHERE 1=1";
        // foreach $filters as $filter {
        // $this->sql .= "AND ($filter['field'] = $filter['criterion1'] OR ...criterion2, etc.)
    }
}

Class ExampleModelDAO extends ORM {
    public function __construct($view, $database, $params) {
       parent::__construct($view, $database);
       // parse params
       parent::mapTables($tables);
       parent::mapFilters($filters);
   }

   public function get() {
      // Prepend $this->sql with SELECT statement specific to model
      //  Query database and return model
   }
}

最佳答案

首先,您的 orm/模型不应该了解有关数据库的任何信息。有一百万种方法可以做到这一点,但我会从一个简单的数据库类开始,它在 pdo 之上提供一些附加功能,但完全独立于其他任何东西。这还允许您直接访问数据库而无需模型,并允许您创建独立于数据库的模型。为了获得最大的灵活性,您需要研究适配器模式和数据映射器。不过,为了简单起见,这里有一个将模型映射到数据存储的非常基本的示例(没有适配器或数据映射器)。

<?php
class DB extends PDO {
    public function __construct() {
        try {
            parent::__construct(/* db info */);
        } catch (Exception $e) {
            // handle the error
        }
    }

    public function read() {
        // read from database
    }

    public function write() {
        // write to database
    }

    // etc...
}

所以你的数据库类将有一些简单的增删改查操作。然后你的 orm 就可以像这样与这个类交互......

<?php
class ORM {
    public function __construct() {
        $this->db = new DB();
    }

    public function find($options) {
        return $this->db->read($options);
    }

    public function save($data) {
        return $this->db->create($data); // or update()
    }

    // etc...
}

这应该足以让你继续下去。另外,如果您不从外部管理连接,则可以使用简单的修改注册表类型模式(请注意,这不是真正的注册表),而不是对数据库使用单例模式。

<?php

class DB extends PDO {
    protected static $instances = array();

    public function __construct() ...

    public static function get($name) {
        if(! isset(self::$instances[$name]) {
            self::$instances[$name] = new self();
        }
        return self::$instances[$name];
    }
}

class ORM {
    public function __construct() {
        $this->db = DB::get('connection1');
    }
}

有更好的方法可以做到这一点,但我将把它留给你。

关于php - 手动滚动 ORM 类——单例、静态父类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9935790/

相关文章:

php - 添加预计交货日期范围?

javascript - 在javascript中从服务器接收文本和图片

php - 为图像主机在 PHP 中阻止隐写术?

java - 在 Java 的 setter 中抛出 Exception 是一种好习惯吗?

javascript - 无法通过ajax将javascript对象传递给php

php - 发布http ://localhost:8000/index/bots 500 (Internal Server Error)

c# - 比 Unsafe.As 转换到子类更好的方法来解决我的类层次结构问题?

php - 如何从变量名动态设置对象的属性?

oop - 形容词的接口(interface)命名

c++ - 深拷贝构造函数数组类C++