我正在为我公司购买的数据仓库编写一个网络报告扩展。数据仓库是数据模型中立的,并且具有存储表关系和字段的元层数据的表。这使得我可以很容易地编写一个基本的 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/