常見(jiàn) PHP ORM 框架與簡(jiǎn)單代碼實(shí)現(xiàn)
對(duì)象關(guān)系映射(Object Relational Mapping,簡(jiǎn)稱ORM)是一種為了解決面向?qū)ο笈c關(guān)系數(shù)據(jù)庫(kù)存在的互不匹配的現(xiàn)象的技術(shù)。 簡(jiǎn)單的說(shuō),ORM是通過(guò)使用描述對(duì)象和數(shù)據(jù)庫(kù)之間映射的元數(shù)據(jù),將程序中的對(duì)象自動(dòng)持久化到關(guān)系數(shù)據(jù)庫(kù)中。本質(zhì)上就是將數(shù)據(jù)從一種形式轉(zhuǎn)換到另外一種形式。
ORM提供了所有SQL語(yǔ)句的生成,代碼人員遠(yuǎn)離了數(shù)據(jù)庫(kù)概念。從一個(gè)概念需求(例如一個(gè)HQL)映射為一個(gè)SQL語(yǔ)句,并不需要什么代價(jià),連1%的性能損失都沒(méi)有。真正的性能損失在映射過(guò)程中,更具體地講,是在對(duì)象實(shí)例化的過(guò)程中。
目前PHP 開(kāi)源比較有名的 ORM 有以下幾個(gè):
1、PropelPropel是一個(gè)適用于PHP5的ORM映射(Object Relational Mapping)框架,它基于Apache Torque提供對(duì)象持久層支持。它通過(guò)XML格式的模式定義文件和相應(yīng)的配置文件來(lái)生成SQL和類,它允許你使用對(duì)象代替SQL來(lái)讀寫數(shù)據(jù)庫(kù)表中的記錄。Propel提供一個(gè)生成器來(lái)為你的數(shù)據(jù)模型創(chuàng)建SQL定義文件和PHP類。開(kāi)發(fā)者也可以十分簡(jiǎn)單的定制生成的類,我們還可以通過(guò)XML, PHP類和Phing構(gòu)建工具把Propel集成到已有的應(yīng)用開(kāi)發(fā)框架中去.例如PHP框架symfony的1.2以前的版本就是默認(rèn)使用了精簡(jiǎn)版的Propel作為默認(rèn)ORM框架。
官方網(wǎng)站:http://www.propelorm.org/
2、DoctrineDoctrine是一個(gè)PHP的ORM框架,它必須運(yùn)行在>=php5.2.3版本上,它是一個(gè)功能強(qiáng)大的數(shù)據(jù)抽象層。
它的一個(gè)主要特征就是使用面向?qū)ο蟮姆绞絹?lái)實(shí)現(xiàn)數(shù)據(jù)庫(kù)查詢的封轉(zhuǎn),它底層通過(guò)一個(gè)類似 Hibernate HQL的DQL的查詢語(yǔ)句進(jìn)行數(shù)據(jù)庫(kù)查詢,這使得開(kāi)發(fā)的靈活性更強(qiáng),大大減小了重復(fù)代碼。相比Propel,Doctrine的優(yōu)點(diǎn)在于它支持支持全文檢索,Doctrine的文檔一直就比Propel要全面豐富,社區(qū)更活躍,而且使用起來(lái)更加自然、更易閱讀、更接近原生SQL。性能方面也略微優(yōu)于Propel。同樣你也可以可以很方便的把Doctrine集成到現(xiàn)有的應(yīng)用框架中去,比如PHP框架symfony的1.3以后的版本將Doctrine作為默認(rèn)的ORM框架,同時(shí)也可以將Doctrine和Codeigniter整合起來(lái)。
官方網(wǎng)站: http://www.doctrine-project.org/
3、EZPDOEZPDO是一個(gè)十分輕量級(jí)的PHP ORM框架。EZPDO的作者的本意旨在降低復(fù)雜的ORM學(xué)習(xí)曲線,盡可能在ORM的運(yùn)行效率和功能之間做一個(gè)平衡點(diǎn),它是我至今用過(guò)的最簡(jiǎn)單的ORM框架,我目前還想將它集成到我的CoolPHP SDK中來(lái),而且運(yùn)行效率相當(dāng)不錯(cuò),功能也基本能滿足需求,只不過(guò)EZPDO的更新比較緩慢。
官方網(wǎng)站:http://www.ezpdo.net/
4、RedBeanRedBean是一個(gè)易于使用,輕量級(jí)PHP ORM框架,提供對(duì)MySQL, SQLite&PostgreSQL的支持。RedBean架構(gòu)非常靈活,核心也非常簡(jiǎn)約,開(kāi)發(fā)者可以很方便的通過(guò)插件來(lái)擴(kuò)展功能。
官方網(wǎng)站:http://www.redbeanphp.com/
5、其他國(guó)內(nèi)的fleaphp開(kāi)發(fā)框架基于TableDataGateway實(shí)現(xiàn)ORM實(shí)現(xiàn);Zend Framework除了提供對(duì) SQL 語(yǔ)句的封裝以外,也同樣實(shí)現(xiàn)了TableGateway、TableRowSet、TableRow的實(shí)現(xiàn);還有一些類似Rails的ActiveRecord實(shí)現(xiàn)的解決方案。
總的來(lái)說(shuō),一般ORM框架對(duì)付簡(jiǎn)單的應(yīng)用系統(tǒng)來(lái)說(shuō)都能滿足基本需求,可以大大降低開(kāi)發(fā)難度,提高開(kāi)發(fā)效率,但是它在SQL優(yōu)化方面,肯定是比純SQL語(yǔ)言要差一些,對(duì)復(fù)雜關(guān)聯(lián)、SQL內(nèi)嵌表達(dá)式的處理可能不是很理想。也許這主要是由于PHP本身對(duì)象持久化的問(wèn)題,導(dǎo)致ORM效率過(guò)低,普遍比純SQL要慢。但是這些都是有辦法解決的,最基本的解決性能的方案,我們可以通過(guò)緩存來(lái)提高效率,Hibernate來(lái)說(shuō),雖然配置比較繁雜,但是它通過(guò)靈活的使用二級(jí)緩存和查詢緩存極大的緩解數(shù)據(jù)庫(kù)的查詢壓力,極大的提升了系統(tǒng)的性能。
如果你想自己實(shí)現(xiàn)一個(gè)PHP的ORM,下面的可以參考下:
<?phpabstract class Model{ protected $pk = ’id’; protected $_ID = null; protected $_tableName; protected $_arRelationMap; protected $_modifyMap; protected $is_load = false; protected $_blForDeletion; protected $_DB; public function __consturct($id = null){ $this->_DB = mysql_connect(’127.0.0.1’,’root’,’’) ; $this->_tableName = $this->getTableName(); $this->_arRelationMap = $this->getRelationMap(); if(isset($id))$this->_ID = $id; } abstract protected function getTableName(); abstract protected function getRelationMap(); public function Load(){ if(isset($this->_ID)){ $sql = 'SELECT '; foreach($this->_arRelationMap as $k => $v){ $sql .= ’`’.$k.’`,’; } $sql .= substr($sql,0,strlen($sql)-1); $sql .= 'FROM '.$this->_tableName.' WHERE '.$this->pk.' = '.$this->_ID; $result =$this->_DB->mysql_query($sql); foreach($result[0] as $k1 => $v1){ $member = $this->_arRelationMap[$key]; if(property_exists($this,$member)){ if(is_numeric($member)){ eval(’$this->’.$member.’ = ’.$value.’;’); }else{ eval(’$this->’.$member.’ = '’.$value.’';’); } } } } $this->is_load = true; } public function __call($method,$param){ $type = substr($method,0,3); $member = substr($method,3); switch($type){ case ’get’: return $this->getMember($member); break; case ’set’: return $this->setMember($member,$param[0]); } return false; } public function setMember($key){ if(property_exists($this,$key)){ if(is_numeric($val)){ eval(’$this->’.$key.’ = ’.$val.’;’); }else{ eval(’$this->’.$key.’ = '’.$val.’';’); } $this->_modifyMap[$key] = 1; }else{ return false; } } public function getMember($key,$val){ if(!$this->is_load){ $this->Load(); } if(property_exists($this,$key)){ eval(’$res = $this->’.$key.’;’ ); return $this->$key; } return false; } public function save(){ if(isset($this->_ID)){ $sql = 'UPDATE '.$this->_tableName.' SET '; foreach($this->arRelationMap as $k2 => $v2){ if(array_key_exists( $k2, $this->_modifyMap)){ eval( ’$val = $this->’.$v2.’;’); $sql_update .= $v2.' = '.$val; } } $sql .= substr($sql_update,0,strlen($sql_update)); $sql .= ’WHERE ’.$this->pk.’ = ’.$this->_ID; }else{ $sql = 'INSERT INTO '.$this->_tableName.' ('; foreach($this->arRelationMap as $k3 => $v3){ if(array_key_exists( $k3,$this->_modifyMap)){ eval(’$val = $this->’.$v3.’;’); $field .= '`'.$v3.'`,'; $values .= $val; } } $fields = substr($field,0,strlen($field)-1); $vals = substr($values,0,strlen($values)-1); $sql .= $fields.' ) VALUES ('.$vals.')'; } echo $sql; //$this->_DB->query($sql); } public function __destory(){ if(isset($this->ID)){ $sql = 'DELETE FROM '.$this->_tableName.' WHERE '.$this->pk.' = '.$this->_ID;// $this->_DB_query($sql); } }}class User extends Model{ protected function getTableName(){ return 'test_user'; } protected function getRelationMap(){return array( ’id’ => USER_ID, ’user_name’=> USER_NAME, ’user_age’ => USER_AGE ); } public function getDB(){ return $this->_DB; }}$UserIns = new User();print_r($UserIns);?>
相關(guān)文章:
1. vue實(shí)現(xiàn)移動(dòng)端返回頂部2. asp讀取xml文件和記數(shù)3. vue 驗(yàn)證兩次輸入的密碼是否一致的方法示例4. xml中的空格之完全解說(shuō)5. 多個(gè)SpringBoot項(xiàng)目采用redis實(shí)現(xiàn)Session共享功能6. python基于scrapy爬取京東筆記本電腦數(shù)據(jù)并進(jìn)行簡(jiǎn)單處理和分析7. python利用opencv實(shí)現(xiàn)顏色檢測(cè)8. CSS自定義滾動(dòng)條樣式案例詳解9. Python如何實(shí)現(xiàn)感知器的邏輯電路10. PHP實(shí)現(xiàn)基本留言板功能原理與步驟詳解
