Php 学习实现基本ORM的技巧/资源/模式
我在这里看到了各种MVC框架以及PHP的独立ORM框架,以及其他ORM问题;然而,大多数问题都要求现有框架开始使用,这不是我想要的。(我也读过,但我不确定该怎么理解,因为答案很模糊。) 相反,我认为我最好的学习方法是弄脏我的手,并实际编写自己的ORM,即使是一个简单的ORM。除了我真的不知道如何开始,特别是因为我在其他ORM中看到的代码非常复杂 通过我的PHP5.2.x(这很重要)MVC框架,我有一个基本的自定义数据库抽象层,它有:Php 学习实现基本ORM的技巧/资源/模式,php,database,model-view-controller,orm,Php,Database,Model View Controller,Orm,我在这里看到了各种MVC框架以及PHP的独立ORM框架,以及其他ORM问题;然而,大多数问题都要求现有框架开始使用,这不是我想要的。(我也读过,但我不确定该怎么理解,因为答案很模糊。) 相反,我认为我最好的学习方法是弄脏我的手,并实际编写自己的ORM,即使是一个简单的ORM。除了我真的不知道如何开始,特别是因为我在其他ORM中看到的代码非常复杂 通过我的PHP5.2.x(这很重要)MVC框架,我有一个基本的自定义数据库抽象层,它有: 非常简单的方法,如connect($host,$user,$
- 非常简单的方法,如
,connect($host,$user,$pass,$base)
,等等query($sql,$binds)
- 它支持的每个DBMS的子类
- 表示SQL结果集的类(以及相应的子类)
- 活动记录功能,我认为这是ORM的东西(如果我错了,请纠正我)
不过,我还是想从其他或多或少涉猎过ORM框架的人那里得到一些简单的提示。还有什么我需要注意的,简单的学术样本供我参考,或者我可以阅读的资源吗?可以使用
\uuuu get()
和\uu set()
以及一些自定义方法(可能使用\uu call()
)构建一个简单的ORM,下面是一个简单的伪代码:
class ORM
{
private $table = null;
private $fields = array();
function __construct($table)
{
$this->table = $table;
}
function __get($key)
{
return isset($this->fields[$key]) ? $this->fields[$key] : false;
}
function __set($key, $value)
{
$this->fields[$key] = $value;
}
function load($id, $field = 'id')
{
// populate $this->fields with SELECT * FROM $this->table WHERE $field = $id;
}
function save()
{
if (isset($this->fields['id']))
{
// UPDATE $this->table SET $this->fields;
}
else
{
// INSERT INTO $this->table $this->fields;
}
}
}
$user = new ORM('user');
$user->name = 'name';
$user->pass = '1337';
$user->save();
这只是一个让您开始学习的基本示例。例如,您可以使用\u call()
magic方法添加进一步的逻辑,以通过id
以外的其他字段获取结果
请记住,我给出的示例不处理关系,这是各种ORM实现的真正不同之处,但是我通常不相信任何ORM能为我处理关系,因为它们往往速度慢得多,并且不会生成有效的查询。因为这个问题很老,我想你已经试过自己写ORM了。尽管如此,两年前我写了一个定制ORM,我仍然想分享我的经验和想法 如前所述,我在两年前实现了一个定制的ORM,甚至在中小型项目中成功地使用了它。我将它集成到一个相当流行的CMS中,当时(甚至现在)还没有ORM功能。此外,在当时,像条令这样的流行框架并没有真正说服我。从那时起,很多东西都发生了变化,并在一个坚实的框架中发展,因此,如果我现在可以选择是实现自己的ORM,还是使用一个流行的框架(如条令2)用于生产,这将毫无疑问——使用现有的、稳定的解决方案。但是:实现这样一个框架(以一种简单的方式)是一个非常有价值的学习练习,它对我使用更大的开源ORM有很大帮助,因为您可以更好地理解与对象关系映射相关的陷阱和困难 实现基本的ORM功能并不太困难,但一旦对象之间的关系映射开始发挥作用,它就会变得非常非常困难/有趣
我是如何开始的? 让我上瘾的是马丁·福勒的书。如果您想编写自己的ORM,或者即使您只是在使用某个ORM框架,请购买本书。它是最有价值的资源之一,涵盖了有关对象关系映射领域的许多基本和高级技术。仔细阅读,你会对ORM背后的模式有很多好的想法 基本架构 我决定是采用一种方法还是某种方法。此决策影响数据库中的数据映射到实体的方式。我决定实现一个简单的数据映射器,与Java使用的方法相同。活动记录是ORM功能(如果可以这样称呼的话)的一种方法。Active Record比数据映射器简单得多,但也有很大的局限性。阅读这些模式并检查上面提到的框架,你很快就会发现它们之间的区别。如果您决定使用数据映射器,您还应该仔细阅读 查询 我有一个雄心勃勃的目标,就是创建自己的查询语言,就像在Doctrine或Hibernate中一样。我很快就放弃了这一点,因为编写定制的SQL解析器/词法分析器似乎太复杂了(事实确实如此!)。我所做的是实现一个,以封装查询中涉及的表的信息(这很重要,因为需要将数据库中的数据映射到每个表的相关类) 在我的ORM中查询对象如下所示:
public function findCountryByUid($countryUid) {
$queryObject = new QueryObject();
$queryObject->addSelectFields(new SelectFields('countries', '*'))
->addTable(new Table('countries'))
->addWhere('countries.uid = "' . intval($countryUid) . '"');
$res = $this->findByQuery($queryObject);
return $res->getSingleResult();
}
配置
通常,您还需要某种配置格式,Hibernate使用XML(以及其他),Doctrine 2使用PHP注释,EZComponents使用PHP数组作为配置格式。这也是我使用的,它看起来是一个自然的选择,我使用的CMS也使用PHP配置格式
通过该配置,您可以定义
- 哪个表映射到哪个类
- 哪些字段应该映射到类实例
- 表的字段有什么类型(int、string等)
- 实体之间的关系(例如,用户类具有对用户组类的引用)