PHP ORM类进行封装

基于PHP简单的ORM实现(postgresql)http://xialluyouyue.iteye.com/blog/2237114

为了减少不必要的数据库查询,对数据库的影响,代码复制,我们需要更加智能方式实现ORM,需要惰性实例化,属性监控,代码可重用性,减少对底层数据库影响以及不必要主动查询的危险。

定义一个DataboundObject类,该类是一个抽象类,不仅提供子类不需要重新生成最终方法(并且,通过final关键字表明该方法不可以重载),还声明了某些必须子类实现的方法,该类可以直接放在工具类中。

命名:DataBoundObject.php

<?php

/* 

 * To change this license header, choose License Headers in Project Properties.

 * To change this template file, choose Tools | Templates

 * and open the template in the editor.

 */

abstract class DataBoundObject {

    

    protected $ID;

    protected $objPDO;

    protected $strTableName;

    protected $arRelationMap;

    protected $blForDeletion;

    protected $blIsLoaded;

    protected $arModifiedRelation;

    

    abstract protected function DefineTableName();

    

    abstract protected function DefineRelationMap();

    

    public function __construct(PDO $objPDO,$id = null) {

        $this->strTableName = $this->DefineTableName();

        $this->arRelationMap = $this->DefineRelationMap();

        $this->objPDO = $objPDO;

        $this->blIsLoaded = false;

        if(isset($id)){

            $this->ID = $id;

        }

        $this->arModifiedRelation = [];

    }

    

    public function load(){

        if(isset($this->ID)){

            $strQuery = "SELECT ";

            foreach ($this->arRelationMap as $key => $value) {

                $strQuery .= "\"".$key."\",";

            }

            $strQuery = substr($strQuery, 0, strlen($strQuery)-1);

            $strQuery .=" FROM ".$this->strTableName." WHERE \"id\" = :eid";

            $objStatement = $this->objPDO->prepare($strQuery);

            $objStatement->bindParam(':eid', $this->ID, PDO::PARAM_INT);

            $objStatement->execute();

            $arRow = $objStatement->fetch(PDO::FETCH_ASSOC);

            foreach ($arRow as $key => $value) {

                $strMember = $this->arRelationMap[$key];

                if(property_exists($this, $strMember)){

                    if(is_numeric($value)){

                        eval('$this->'.$strMember .' = '.$value.';');

                    }else{

                        eval('$this->'.$strMember.' = "'.$value.'";');

                    }

                }

            }

            $this->blIsLoaded = true;

        }

    }

    

    public function Save(){

        

        if(isset($this->ID)){

            $strQuery = 'UPDATE "'.$this->strTableName.'" SET ';

            foreach ($this->arRelationMap as $key => $value) {

                eval('$actualVal = &$this->'.$value.';');

                if(array_key_exists($value, $this->arModifiedRelation)){

                    $strQuery .= '"' .$key. "\" = :$value,";

                }

            }

            $strQuery = substr($strQuery, 0,strlen($strQuery)-1);

            $strQuery .=' WHERE "id"=:eid';

            unset($objStatement);

            $objStatement = $this->objPDO->prepare($strQuery);

            $objStatement->bindValue(':eid', $this->ID,  PDO::PARAM_INT);

            

            foreach ($this->arRelationMap as $key => $value) {

                eval('$actualVal = &$this->'.$value.';');

                

                if(array_key_exists($value, $this->arModifiedRelation)) {

                    if(is_int($actualVal)){

                        $objStatement->bindValue(':'.$value, $this->$value, PDO::PARAM_INT);

                    }elseif($actualVal == NULL){

                        //postgresql:if some column type is null,update will cause error,u need insert null,not ''

                        $objStatement->bindValue(':'.$value, NULL, PDO::PARAM_STR);

                    }else{

                        $objStatement->bindValue(':'.$value, $this->$value, PDO::PARAM_STR);

                    }

                }

            }

            $objStatement->execute();

            echo '更新成功';exit;

        }else{

            $strValueList = "";

            $strQuery = 'INSERT INTO "'.$this->strTableName.'" (';

            

            foreach ($this->arRelationMap as $key => $value) {

                eval('$actualVal = &$this->'.$value.';');

                

                if(isset($actualVal)){

                    if(array_key_exists($value, $this->arModifiedRelation)){

                        $strQuery .= '"' .$key. '",';

                        $strValueList .= ":$value,";

                    }

                    

                }

            }

            $strQuery = substr($strQuery, 0, strlen($strQuery)-1);

            $strValueList = substr($strValueList, 0, strlen($strValueList)-1);

            $strQuery .= ") VALUES (";

            $strQuery .= $strValueList;

            $strQuery .= ")";

            unset($objStatement);

            $objStatement = $this->objPDO->prepare($strQuery);

            foreach ($this->arRelationMap as $key => $value) {

                eval('$actualVal = &$this->'.$value.';');

                if(isset($actualVal)){

                    if(array_key_exists($value, $this->arModifiedRelation)){

                        if(is_int($actualVal) || $actualVal == NULL){

                            $objStatement->bindValue(':'.$value, $actualVal, PDO::PARAM_INT);

                        }else{

                            $objStatement->bindValue(':'.$value, $actualVal, PDO::PARAM_STR);

                        }

                    }

                }

            }

            

            $objStatement->execute();

            $this->ID = $this->objPDO->lastInsertId($this->strTableName."_id_seq");

        }

    }

    

    public function MarkFordeletion(){

        $this->blForDeletion = true;

    }

    

    public function __destruct() {

        if(isset($this->ID)){

            if($this->blForDeletion == true){

                $strQuery = 'DELETE FROM "'.$this->strTableName.'" WHERE "id" =:eid';

                $objStatement = $this->objPDO->prepare($strQuery);

                $objStatement->bindValue(':eid', $this->ID,  PDO::PARAM_INT);

                $objStatement->execute();

                echo '删除成功';exit;

            }

        }

    }

    

    public function __call($strFunction, $arArguments) {

        $strMethodType = substr($strFunction, 0,3);

        $strMethodMember = substr($strFunction, 3);

        switch ($strMethodType) {

            case 'set':

                return ($this->SetAccessor($strMethodMember, $arArguments[0]));

                break;

            case 'get':

                return ($this->GetAccessor($strMethodMember));

        }

        return (false);

    }

    

    private function SetAccessor($strMember,$strNewValue){

        if(property_exists($this, $strMember)){

            if(is_numeric($strNewValue)){

                eval('$this->'.$strMember.' = '.$strNewValue.';');

            }else{

                eval('$this->'.$strMember.' = "'.$strNewValue.'";');

            }

            $this->arModifiedRelation[$strMember] = "1";

        }else{

            return (false);

        }

    }

    

    private function GetAccessor($strMember){

        if($this->blIsLoaded != true){

            $this->load();

        }

        

        if(property_exists($this, $strMember)){

            eval('$strRetVal = $this->'.$strMember.';');

            return ($strRetVal);

        }else{

            return (false);

        }

    } 

}

我们还是用system_user表(postgresql)

定义User类进行继承DataBoundObject类,

命名User.php

<?php

/* 

 * To change this license header, choose License Headers in Project Properties.

 * To change this template file, choose Tools | Templates

 * and open the template in the editor.

 */

require_once 'DataBoundObject.php';

class User extends DataBoundObject{

    

    protected $FirstName;

    protected $LastName;

    protected $Username;

    protected $Password;

    protected $EmailAddress;

    

    protected $DateLastLogin;

    protected $TimeLastLogin;

    protected $DateAccountCreated;

    protected $TimeAccountCreated;

    

    protected function DefineTableName() {

        return ("system_user");

    }

    

    protected function DefineRelationMap() {

        return ([

            "id"                    => "ID",

            "first_name"            => "FirstName",

            "last_name"             => "LastName",

            "username"              => "Username",

            "md5_pw"                => "password",

            "email_address"         => "EmailAddress",

            "date_last_login"       => "DateLastLogin",

            "time_last_login"       => "TimeLastLogin",

            "date_account_created"  => "DateAccountCreated",

            "time_account_created"  => "TimeAccountCreated"

        ]);

    }  

}

下面我们进行测试:

命名为TestSystemUser.php

<?php

/* 

 * To change this license header, choose License Headers in Project Properties.

 * To change this template file, choose Tools | Templates

 * and open the template in the editor.

 */

require_once 'PdoFactory.php';

require_once 'DataBoundObject.php';

require_once 'User.php';

$dsn ="pgsql:host=192.168.1.234;port=5432;dbname=dbname;";

$objPdo = PdoFactory::getPDO($dsn,'postgres','123456',[]);

$objUser = new User($objPdo);

$objUser->setFirstName('Kavin');

$objUser->setLastName('Green');

$objUser->setDateAccountCreated(date('Y-m-d'));

print "First name is ".$objUser->getFirstName()."<br />";

print "Last name is ".$objUser->getLastName()."<br />";

$objUser->Save();

$id = $objUser->getID();

print "ID in database is".$id."<br />";

unset($objUser);

$objUser = new User($objPdo,$id);

$objUser->setFirstName('Tobo11');

$objUser->setLastName('Jimlin111');

print "Saving.....";

$objUser->Save();

测试结果

First name is Kavin
Last name is Green
ID in database is18
Saving.....更新成功

上述基本是ORM实现基本原理,需要进一步进行该进,只是测试用。

 

猜你喜欢

转载自xialluyouyue.iteye.com/blog/2237608