对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。
ORM提供了所有SQL语句的生成,代码人员远离了数据库概念。从一个概念需求(例如一个HQL)映射为一个SQL语句,并不需要什么代价,连1%的性能损失都没有。真正的性能损失在映射过程中,更具体地讲,是在对象实例化的过程中。
目前PHP 开源比较有名的 ORM 有以下几个:
1、Propel
Propel是一个适用于PHP5的ORM映射(Object Relational Mapping)框架,它基于Apache Torque提供对象持久层支持。它通过XML格式的模式定义文件和相应的配置文件来生成SQL和类,它允许你使用对象代替SQL来读写数据库表中的记录。Propel提供一个生成器来为你的数据模型创建SQL定义文件和PHP类。开发者也可以十分简单的定制生成的类,我们还可以通过XML, PHP类和Phing构建工具把Propel集成到已有的应用开发框架中去.例如PHP框架symfony的1.2以前的版本就是默认使用了精简版的Propel作为默认ORM框架。
官方网站:http://www.propelorm.org/
2、Doctrine
Doctrine是一个PHP的ORM框架,它必须运行在>=php5.2.3版本上,它是一个功能强大的数据抽象层。
它的一个主要特征就是使用面向对象的方式来实现数据库查询的封转,它底层通过一个类似 Hibernate HQL的DQL的查询语句进行数据库查询,这使得开发的灵活性更强,大大减小了重复代码。相比Propel,Doctrine的优点在于它支持支持全文检索,Doctrine的文档一直就比Propel要全面丰富,社区更活跃,而且使用起来更加自然、更易阅读、更接近原生SQL。性能方面也略微优于Propel。同样你也可以可以很方便的把Doctrine集成到现有的应用框架中去,比如PHP框架symfony的1.3以后的版本将Doctrine作为默认的ORM框架,同时也可以将Doctrine和Codeigniter整合起来。
官方网站: http://www.doctrine-project.org/
3、EZPDO
EZPDO是一个十分轻量级的PHP ORM框架。EZPDO的作者的本意旨在降低复杂的ORM学习曲线,尽可能在ORM的运行效率和功能之间做一个平衡点,它是我至今用过的最简单的ORM框架,我目前还想将它集成到我的CoolPHP SDK中来,而且运行效率相当不错,功能也基本能满足需求,只不过ESPDO的更新比较缓慢。
官方网站:http://www.ezpdo.net/blog/?p=2
4、RedBean
RedBean是一个易于使用,轻量级PHP ORM框架,提供对MySQL, SQLite&PostgreSQL的支持。RedBean架构非常灵活,核心也非常简约,开发者可以很方便的通过插件来扩展功能。
官方网站:http://www.redbeanphp.com/
5、其他
国内的fleaphp开发框架基于TableDataGateway实现ORM实现;Zend Framework除了提供对 SQL 语句的封装以外,也同样实现了TableGateway、TableRowSet、TableRow的实现;还有一些类似Rails的ActiveRecord实现的解决方案。
总的来说,一般ORM框架对付简单的应用系统来说都能满足基本需求,可以大大降低开发难度,提高开发效率,但是它在SQL优化方面,肯定是比纯SQL语言要差一些,对复杂关联、SQL内嵌表达式的处理可能不是很理想。也许这主要是由于PHP本身对象持久化的问题,导致ORM效率过低,普遍比纯SQL要慢。但是这些都是有办法解决的,最基本的解决性能的方案,我们可以通过缓存来提高效率,Hibernate来说,虽然配置比较繁杂,但是它通过灵活的使用二级缓存和查询缓存极大的缓解数据库的查询压力,极大的提升了系统的性能。
如果你想自己实现一个PHP的ORM,下面的可以参考下:
002 |
abstract class Model{ |
003 |
protected $pk = 'id' ; |
004 |
protected $_ID = null; |
005 |
protected $_tableName ; |
006 |
protected $_arRelationMap ; |
007 |
protected $_modifyMap ; |
008 |
protected $is_load = false; |
009 |
protected $_blForDeletion ; |
012 |
public function __consturct( $id = null){ |
013 |
$this ->_DB = mysql_connect( '127.0.0.1' , 'root' , '' ) ; |
014 |
$this ->_tableName = $this ->getTableName(); |
015 |
$this ->_arRelationMap = $this ->getRelationMap(); |
016 |
if (isset( $id )) $this ->_ID = $id ; |
018 |
abstract protected function getTableName(); |
019 |
abstract protected function getRelationMap(); |
021 |
public function Load(){ |
022 |
if (isset( $this ->_ID)){ |
024 |
foreach ( $this ->_arRelationMap as $k => $v ){ |
027 |
$sql .= substr ( $sql ,0, strlen ( $sql )-1); |
028 |
$sql .= "FROM " . $this ->_tableName. " WHERE " . $this ->pk. " = " . $this ->_ID; |
029 |
$result = $this ->_DB->mysql_query( $sql ); |
030 |
foreach ( $result [0] as $k1 => $v1 ){ |
031 |
$member = $this ->_arRelationMap[ $key ]; |
032 |
if (property_exists( $this , $member )){ |
033 |
if ( is_numeric ( $member )){ |
034 |
eval ( '$this->' . $member . ' = ' . $value . ';' ); |
036 |
eval ( '$this->' . $member . ' = "' . $value . '";' ); |
041 |
$this ->is_load = true; |
043 |
public function __call( $method , $param ){ |
044 |
$type = substr ( $method ,0,3); |
045 |
$member = substr ( $method ,3); |
048 |
return $this ->getMember( $member ); |
051 |
return $this ->setMember( $member , $param [0]); |
055 |
public function setMember( $key ){ |
056 |
if (property_exists( $this , $key )){ |
057 |
if ( is_numeric ( $val )){ |
058 |
eval ( '$this->' . $key . ' = ' . $val . ';' ); |
060 |
eval ( '$this->' . $key . ' = "' . $val . '";' ); |
062 |
$this ->_modifyMap[ $key ] = 1; |
068 |
public function getMember( $key , $val ){ |
072 |
if (property_exists( $this , $key )){ |
073 |
eval ( '$res = $this->' . $key . ';' ); |
079 |
public function save(){ |
080 |
if (isset( $this ->_ID)){ |
081 |
$sql = "UPDATE " . $this ->_tableName. " SET " ; |
082 |
foreach ( $this ->arRelationMap as $k2 => $v2 ){ |
083 |
if ( array_key_exists ( $k2 , $this ->_modifyMap)){ |
084 |
eval ( '$val = $this->' . $v2 . ';' ); |
085 |
$sql_update .= $v2 . " = " . $val ; |
088 |
$sql .= substr ( $sql_update ,0, strlen ( $sql_update )); |
089 |
$sql .= 'WHERE ' . $this ->pk. ' = ' . $this ->_ID; |
091 |
$sql = "INSERT INTO " . $this ->_tableName. " (" ; |
092 |
foreach ( $this ->arRelationMap as $k3 => $v3 ){ |
093 |
if ( array_key_exists ( $k3 , $this ->_modifyMap)){ |
094 |
eval ( '$val = $this->' . $v3 . ';' ); |
095 |
$field .= "`" . $v3 . "`," ; |
099 |
$fields = substr ( $field ,0, strlen ( $field )-1); |
100 |
$vals = substr ( $values ,0, strlen ( $values )-1); |
101 |
$sql .= $fields . " ) VALUES (" . $vals . ")" ; |
104 |
//$this->_DB->query($sql); |
106 |
public function __destory(){ |
107 |
if (isset( $this ->ID)){ |
108 |
$sql = "DELETE FROM " . $this ->_tableName. " WHERE " . $this ->pk. " = " . $this ->_ID; |
109 |
// $this->_DB_query($sql); |
114 |
class User extends Model{ |
115 |
protected function getTableName(){ |
118 |
protected function getRelationMap(){ |
121 |
'user_name' => USER_NAME, |
122 |
'user_age' => USER_AGE |
125 |
public function getDB(){ |
130 |
$UserIns = new User(); |
- 【Idea插件】kotlin的orm框架一键生成代码框架
@font-face { font-family: octicons-link; src: url("data:font/woff;charset=utf-8;base64,d09GRgAB ...
- .net ORM框架(Dapper简单应用)
1.引入 Dapper.dll类库 2.创建书籍模型book using System; using System.Collections.Generic; using System.Linq; us ...
- ent facebook 开源的golang orm 框架
ent 是facebook 开源的golang orm 框架,简单强大,具有提下特性 schema 即代码 方便的图遍历 静态类型以及显示api 多种存储引擎支持(当前是mysql,sqlite,以及 ...
- Android orm 框架xUtils简介
数据库操作建议用ORM框架,简单高效.这里推荐xUtils,里面包含DBUtils.github地址:https://github.com/wyouflf/xUtils 获得数据库实例建议用单例模式. ...
- 一行代码调用实现带字段选取+条件判断+排序+分页功能的增强ORM框架
问题:3行代码 PDF.NET是一个开源的数据开发框架,它的特点是简单.轻量.快速,易上手,而且是一个注释完善的国产开发框架,受到不少朋友的欢迎,也在我们公司的项目中多次使用.但是,PDF.NET比起 ...
- 简单实用的Android ORM框架TigerDB
TigerDB是一个简单的Android ORM框架,它能让你一句话实现数据库的增删改查,同时支持实体对象的持久化和自动映射,同时你也不必关心表结构的变化,因为它会自动检测新增字段来更新你的表结构. ...
- 封装JDBC:实现简单ORM框架lfdb
作者:Vinkn 来自http://www.cnblogs.com/Vinkn/ 一.简介 框架就是一组可重用的构件,LZ自己写的姑且就叫微型小框架:lfdb.LZ也对其他的ORM框架没有什么了解,现 ...
- ASP.NET MVC 使用 Petapoco 微型ORM框架+NpgSql驱动连接 PostgreSQL数据库
前段时间在园子里看到了小蝶惊鸿 发布的有关绿色版的Linux.NET——“Jws.Mono”.由于我对.Net程序跑在Linux上非常感兴趣,自己也看了一些有关mono的资料,但是一直没有时间抽出时间 ...
- 最好的5个Android ORM框架
在开发Android应用时,保存数据有这么几个方式, 一个是本地保存,一个是放在后台(提供API接口),还有一个是放在开放云服务上(如 SyncAdapter 会是一个不错的选择). 对于第一种方式, ...
随机推荐
- JS 打字机效果
请点我,查看效果 我送过你礼物 试过对你不管不顾 我挂过你电话 也曾为你哭到沙哑 我曾经为你去学做过晚餐 曾觉得你的关心太烦 也曾为你起得很早 试过狠心把你甩掉 试过偷偷拍你的微笑 也曾经把你电话删掉 ...
- [前端笔记]第三篇:JavaScript
JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏览器可以解释并做出相应的处理. 一.代码存放位置 J ...
- python内置字符串操作方法
1.capitalize() S.capitalize()->string 首字母大写,其余字母小写. str='A222aaA' str.capitalize()#首字母大写,其余字母小写. ...
- MapReduce程序开发之流量求和(八)
1.分析记录手机流量的日志. 2.拿到日志中的一行数据,切分各个字段,抽取出我们需要的字段:手机号,上行流量,下行流量,然后封装成kv发送出去 3.使用java中的map方法: public clas ...
- asp.net web api long running task
http://stackoverflow.com/questions/17577016/long-running-task-in-webapi http://blog.stephencleary.co ...
- JavaScript API
HTML5 DOM, BOM, XMLHttpRequest, NodeJS, Framework Framework---------------> jQuery zepto Undersco ...
- Response对象
Response对象来自HttpResponse类,它用于向客户端输出信息或设置客户端输出状态,使用Response对象可以直接发送信息给浏览器.重定向浏览器到另一个URL或设置cookie的值等. ...
- Java中的移位操作符
记住所有的移动位数,针对的都是补码来讲的,所以要先将十进制整数转换成补码后,然后再来进行移位操作 移位操作 还要注意类型的约束条件,例如int,移动范围是0-31位,所以看补码只能看最后五位,这才是有 ...
- Lua table使用
days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Th ...
- c语言小练习(蛮好玩的)
1.求三个数的平均数,要求保留三位小数位 #include <conio.h> #include<stdio.h> int main(){ int a,b,c; float a ...