數(shù)據(jù)庫(kù)操作:基于NotORM的使用及優(yōu)化

2018-11-21 21:14 更新

有些裁縫只會(huì)塞塞襯里,修修補(bǔ)補(bǔ),而有些裁縫卻能做出新東西--他們之間隔著一條深淵。 -- 《外套》

1.15.1 NotORM官網(wǎng)

這里使用了NotORM進(jìn)行DB操作,具體的數(shù)據(jù)庫(kù)操作使用文檔請(qǐng)見(jiàn)NotORM官網(wǎng): http://www.notorm.com

(1) 基本CURD

//查詢(xún)
$row = DI()->notorm->user->where('id', 1)->fetch();

//更新
$data = array('name' => 'test', 'update_time' => time());
DI()->notorm->user->where('id', 1)->update($data);

//插入(須是同一個(gè)對(duì)象才能正確獲取插入的ID)
$data = array('name' => 'phalapi');
$userORM = DI()->notorm->user;
$userORM->insert($data);
$id = $userORM->insert_id();

//刪除
DI()->notorm->user->where('id', 1)->delete();

(2)update相同的數(shù)據(jù)的判斷

在使用update操作時(shí),如果更新的數(shù)據(jù)和原來(lái)的一樣,則會(huì)返回0(影響0行)。這時(shí),會(huì)和更新失?。ㄍ瑯佑绊?行)混淆。

但NotORM是一個(gè)優(yōu)秀的類(lèi)庫(kù),所以提供了優(yōu)秀的解決文案。我們?cè)谑褂胾pdate時(shí),只須了解這兩者返回的結(jié)果的微妙區(qū)別即可。
因?yàn)槭‘惓r(shí),返回false;而相同數(shù)據(jù)更新會(huì)返回0。即:

  • 1、update相同的數(shù)據(jù)時(shí),返回0,嚴(yán)格來(lái)說(shuō)是:int(0)
  • 2、update失敗時(shí),如更新一個(gè)不存在的字段,返回false,即:bool(false)

用代碼表示,就是:

$rs = DI()->notorm->user->where('id', $userId)->update($data);

if ($rs >= 1) {
    //成功
} else if ($rs === 0) {
    //相同數(shù)據(jù),無(wú)更新
} else if ($rs === false) {
    //更新失敗
}

以下單元測(cè)試代碼,可以驗(yàn)證上面的判斷:

    public function testUpdateOk()
    {
        $userId = 87;

        $rs = DI()->notorm->user->where('id', $userId)->update(array('reg_time' => time()));

        $this->assertSame(1, $rs);
    }

    public function testUpdateZero()
    {
        $userId = 1;

        $rs = DI()->notorm->user->where('id', $userId)->update(array('username' => 'aevit'));

        $this->assertSame(0, $rs);
    }

    public function testUpdateFail()
    {
        $userId = 1;

        $rs = DI()->notorm->user->where('id', $userId)->update(array('wrong_username' => 'aevit'));

        $this->assertSame(FALSE, $rs);
    }

(3)簡(jiǎn)單的關(guān)聯(lián)查詢(xún)

如果是簡(jiǎn)單的關(guān)聯(lián)查詢(xún),可以使用NotORM支持的寫(xiě)法,這樣的好處在于我們使用了一致的開(kāi)發(fā),并且能讓PhalApi框架保持分布式的操作方式(注意,關(guān)聯(lián)的表仍然需要在同一個(gè)數(shù)據(jù)庫(kù))。

以下是一個(gè)簡(jiǎn)單的示例。

假設(shè)我們有這樣的數(shù)據(jù):

INSERT INTO `phalapi_user` VALUES ('1', 'wx_edebc877070133c65161d00799e00544', 'weixinName', '******', '4CHqOhe1Jxi3X9HmRfPOXygDnU267eCA', '1431790647', 'phpunit.png');
INSERT INTO `phalapi_user_session_0` VALUES ('1', '1', 'ABC', '', '0', '0', '0', null);

那么對(duì)應(yīng)關(guān)聯(lián)查詢(xún)的代碼如下面:

    public function testLeftJoin()
    {
        $rs = DI()->notorm->user_session_0
            ->select('expires_time, user.username, user.nickname')
            ->where('token', 'ABC')
            ->fetchRow();

        var_dump($rs);
    }

運(yùn)行一下,我們可以看到這樣的輸出:

SELECT expires_time, user.username, user.nickname FROM phalapi_user_session_0 LEFT JOIN phalapi_user AS user ON phalapi_user_session_0.user_id = user.id WHERE (token = 'ABC') LIMIT 1;

.[1 - 0.06318s]SELECT expires_time, user.username, user.nickname FROM phalapi_user_session_0 LEFT JOIN phalapi_user AS user ON phalapi_user_session_0.user_id = user.id WHERE (token = 'ABC') LIMIT 1;<br>
array(3) {
  ["expires_time"]=>
  string(1) "0"
  ["username"]=>
  string(35) "wx_edebc877070133c65161d00799e00544"
  ["nickname"]=>
  string(10) "weixinName"
}

這樣,我們就可以實(shí)現(xiàn)關(guān)聯(lián)查詢(xún)的操作。按照NotORM官網(wǎng)的說(shuō)法,則是:

If the dot notation is used for a column anywhere in the query ("$table.$column") then NotORM automatically creates left join to the referenced table. Even references across several tables are possible ("$table1.$table2.$column"). Referencing tables can be accessed by colon: $applications->select("COUNT(application_tag:tag_id)").

->select('expires_time, user.username, user.nickname')這一行調(diào)用將會(huì)【自動(dòng)產(chǎn)生關(guān)聯(lián)操作】,而ON 的字段,則是這個(gè)字段關(guān)聯(lián)你配置的【表結(jié)構(gòu)】,外鍵默認(rèn)為: 表名_id 。

(4)加1操作

NotORM已提供了NotORM_Literal,其用法如下:

DI()->notorm->user->where('id', 1)->update(array('age' => new NotORM_Literal("age + 1")));

當(dāng)需要更新為當(dāng)前時(shí)間,可以:

$array = array(
    "title" => "NotORM",
    "author_id" => null,
    "created" => new NotORM_Literal("NOW()"),
);

1.15.2 NotORM的優(yōu)化

但為了更符合項(xiàng)目的開(kāi)發(fā),這里對(duì)NotORM的底層作了升級(jí)修改,以下為主要修改點(diǎn)和新的使用:

(1)將原來(lái)返回的結(jié)果全部從對(duì)象改成數(shù)組

對(duì)原來(lái)的大部分使用無(wú)特別影響,可按原來(lái)的方式開(kāi)發(fā)。主要目的是為了更方面處理返回的數(shù)據(jù),以及簡(jiǎn)化對(duì)結(jié)果的再解析,簡(jiǎn)單明了。
如:

DI()->notorm->user->where('username = ?', 'dogstar')->fetch();

返回的將是一個(gè)數(shù)組:

array(7) {
  ["id"]=>
  string(3) "180"
  ["username"]=>
  string(17) "dogstar"
  ["regtime"]=>
  string(10) "1414811954"
  //...
}

(2)提供獲取全部結(jié)果的接口 - fetchAll() / fetchRows()

如:

$rows = DI()->notorm->event_picurl->where('eid', $eids)->fetchAll();

或:

$rows = DI()->notorm->event_picurl->where('eid', $eids)->fetchRows();

即可獲取全部的數(shù)據(jù),不再受限于分頁(yè)。
這里提供了fetchAll()和fetchRows()兩種等效的操作,是為了減少記憶的痛苦,下同。

(3)提供更靈活的查詢(xún)方式 - queryAll() / queryRows()

當(dāng)需要進(jìn)行復(fù)雜的SQL查詢(xún)時(shí),可以使用此接口,如:
(注意:limit替換值:start和:num必須使用int類(lèi)型)

$sql = 'select * from example AS ep LEFT JOIN user AS u ON ep.ui
d = u.id  where ep.touid = :userId ORDER BY dateline desc LIMIT :start,:num';
$params = array(':userId' => $userId, ':start' => $start, ':num' => $num);
$rs= DI()->notorm->example->queryAll($sql, $params);

或:

$rs= DI()->notorm->example->queryRows($sql, $params);

(4)limit 操作的調(diào)整

取消了NotORM中對(duì)OFFSET關(guān)鍵字的使用,改用逗號(hào)的寫(xiě)法,修改后正確的使用方法應(yīng)該是:

$table->limit(10);  // limit 10   # 查詢(xún)前10個(gè)

$table->limit(5, 10); // limit 5,10   # 從第5個(gè)位置開(kāi)始,查詢(xún)前10個(gè)

(5)禁止全表刪除,防止誤刪

出于對(duì)數(shù)據(jù)的保護(hù),當(dāng)執(zhí)行刪除操作卻又沒(méi)有任何where條件時(shí),將會(huì)禁止進(jìn)行全表操作。如:

    public function testDeleteAll()
    {
        DI()->notorm->user->delete();
    }

可以看到:

$ phpunit --filter testDeleteAll ./Api/Api_User_Test.php 
PHPUnit 4.3.4 by Sebastian Bergmann.

E

Time: 315 ms, Memory: 6.25Mb

There was 1 error:

1) PhpUnderControl_ApiUser_Test::testDeleteAll
Exception: sorry, you can not delete the whole table --dogstar

(6)添加& __sql__ =1請(qǐng)求參數(shù),可開(kāi)啟HTTP調(diào)試模式

當(dāng)處于debug模式時(shí),可以輸入執(zhí)行的全部SQL語(yǔ)句,以便調(diào)試。

如:

SELECT times FROM tpl_user_session_10 WHERE (user_id = ?); -- '74110'
{"ret":0,"data":{"code":0},"msg":""}

(7)關(guān)于NotORM中fetch()操作沒(méi)有l(wèi)imit 1的處理方案 - fetchOne() / fetchRow()

之前,有開(kāi)發(fā)同學(xué)提及到,為什么notorm的基類(lèi)fetch為啥沒(méi)用limit(1)呢。后來(lái),我去發(fā)了下NotORM的寫(xiě)法,確實(shí)做得很微妙。
其實(shí)NotORM之所以沒(méi)有在fetch()里面自動(dòng)limit 1是因?yàn)?,你可以循環(huán)地獲取數(shù)據(jù),如:

$user = DI()->notorm->user->select('id, username, nickname')->where('id > ?', 0)->limit(3);
while(($row = $user->fetch())) {
    var_dump($row);
 }

但是,更多情況下,我們只需要獲取某一行的數(shù)據(jù),上面的做法會(huì)造成不必要的SQL查詢(xún)。為了保留原來(lái)的寫(xiě)法,我特意添加擴(kuò)展了一個(gè)新的操作:fetchRow(),用法同fetch(),但只會(huì)取第一條。
以下是使用示例:

$rs = DI()->notorm->user->select('id, username, nickname')->where('id > ?', 0)->fetchRow());

var_dump($rs);

//結(jié)果輸出類(lèi)如:
array(3) {
  ["id"]=>
  string(1) "1"
  ["username"]=>
  string(5) "aevit"
  ["nickname"]=>
  string(4) "test"
}

//對(duì)應(yīng)執(zhí)行的SQL語(yǔ)句:
[2 - 0.06544s]SELECT id, username, nickname FROM fami_user WHERE (id > ?) LIMIT 1; -- 0<br>

如果,我們只需要獲取這一行的某個(gè)字段,也可以像fecth()那樣使用,即:

$rs = DI()->notorm->user->select('id, username, nickname')->where('id > ?', 0)->fetchRow('nickname'));

var_dump($rs);

//結(jié)果輸出類(lèi)如:
string(4) "test"

//紀(jì)錄不存在時(shí),返回 bool(false)

(8)顯式的SQL語(yǔ)法異常提示

很多時(shí)候,在開(kāi)發(fā)時(shí),我們對(duì)數(shù)據(jù)庫(kù)操作一開(kāi)始會(huì)存在一些SQL語(yǔ)法的問(wèn)題,PDO會(huì)返回false,且原來(lái)NotORM也是使用 靜默方式 來(lái)處理這類(lèi)錯(cuò)誤,從而使得開(kāi)發(fā)人員有時(shí)難以發(fā)現(xiàn)這些問(wèn)題,除非將調(diào)試的SQL手動(dòng)放到數(shù)據(jù)庫(kù)執(zhí)行才能發(fā)現(xiàn)問(wèn)題所在。

為了能給開(kāi)發(fā)同學(xué)更早、更直觀的方式查看問(wèn)題的所在,這里對(duì)NotORM底層進(jìn)行了調(diào)整,使用了 顯式方式 的策略來(lái)處理,即:直接拋出PDO異常。

如:

$userId = 1;

//OK
$rs = DI()->notorm->user->select('username')->where('id', $userId)->fetchOne();

//WRONG
$rs = DI()->notorm->user->select('wrong_username')->where('id', $userId)->fetchOne();

將會(huì)看到:

[1 - 0.06437s]SELECT username FROM fami_user WHERE (id = 1) LIMIT 1;<br>
[2 - 0.06496s]SELECT wrong_username FROM fami_user WHERE (id = 1) LIMIT 1;<br>

PDOException: Unknown column 'wrong_username' in 'field list'

(9)復(fù)雜的關(guān)聯(lián)查詢(xún)

如果是復(fù)雜的關(guān)聯(lián)查詢(xún),則是建議使用原生態(tài)的SQL語(yǔ)句,但我們?nèi)匀豢梢员3趾芎玫膶?xiě)法,如這樣一個(gè)示例:

        $sql = 'SELECT t.id, t.team_name, v.vote_num '
            . 'FROM phalapi_team AS t LEFT JOIN phalapi_vote AS v '
            . 'ON t.id = v.team_id '
            . 'ORDER BY v.vote_num DESC';
        $rows = $this->getORM()->queryAll($sql, array());

注意,此時(shí)的表需要使用全名,即自帶前綴。這樣也可以實(shí)現(xiàn)更自由的關(guān)聯(lián)查詢(xún)。

(10)事務(wù)操作

關(guān)于事務(wù)操作,可以參考 NotORM官網(wǎng) 的說(shuō)明:

$db->transaction = $command Assign 'BEGIN', 'COMMIT' or 'ROLLBACK' to start or stop transaction 

即:

//第一步:先指定待進(jìn)行事務(wù)的數(shù)據(jù)庫(kù)(通過(guò)獲取一個(gè)notorm表實(shí)例來(lái)指定;否則會(huì)提示:PDO There is no active transaction)
$user = DI()->notorm->user;

//第二步:開(kāi)啟事務(wù)開(kāi)關(guān)(此開(kāi)關(guān)會(huì)將當(dāng)前全部打開(kāi)的數(shù)據(jù)庫(kù)都進(jìn)行此設(shè)置)
DI()->notorm->transaction = 'BEGIN';

//第三步:進(jìn)行數(shù)據(jù)庫(kù)操作
$user->insert(array('name' => 'test1',));
$user->insert(array('name' => 'test2',));

//第四:提交/回滾
DI()->notorm->transaction = 'COMMIT';
//DI()->notorm->transaction = 'ROLLBACK';

推薦使用PhalApi的事務(wù)操作方式

PhalApi一開(kāi)始對(duì)事務(wù)這塊考慮不周,后來(lái)發(fā)現(xiàn)很多同學(xué)、很多項(xiàng)目都需要用到數(shù)據(jù)庫(kù)事務(wù)操作。
基于此,在不破壞原來(lái)的代碼基礎(chǔ)上,我們決定在PhalApi_DB_NotORM上添加對(duì)數(shù)據(jù)庫(kù)維度的事務(wù)操作支持。

示例簡(jiǎn)單如下:

    public function testTransactionCommit()
    {
        //Step 1: 開(kāi)啟事務(wù)
        $this->notorm->beginTransaction('db_demo');

        //Step 2: 數(shù)據(jù)庫(kù)操作
        $this->notorm->user>insert(array('name' => 'test1'));
        $this->notorm->user>insert(array('name' => 'test2'));

        //Step 3: 提交事務(wù)
        $this->notorm->commit('db_demo');

    }

溫馨提示: 以上操作,須PhalApi 1.3.1 及以上版本才能支持。

(11)擴(kuò)展對(duì)非MySQL數(shù)據(jù)庫(kù)的支持

PhalApi使用的是NotORM來(lái)進(jìn)行數(shù)據(jù)庫(kù)操作,而NotORM底層則是采用了PDO。目前,NotORM支持: MySQL, SQLite, PostgreSQL, MS SQL, Oracle (Dibi support is obsolete)。

但需要注意的是,PhalApi本身對(duì)NotORM進(jìn)行了修改,需要調(diào)整一下代碼才能更好地支持除MySQL外的數(shù)據(jù)庫(kù)。即使NotORM不支持的數(shù)據(jù)庫(kù),你也可以輕松通過(guò)添加擴(kuò)展的方式來(lái)支持。如:

首先,定制自己的數(shù)據(jù)庫(kù)連接的PDO。

class Common_MyDB extends PhalApi_DB_NotORM {

    protected function createPDOBy($dbCfg) {
        /* Connect to an ODBC database using driver invocation */
    $dsn = 'uri:file:///usr/local/dbconnect';
    return new PDO($dsn, $dbCfg['user'], $dbCfg['password']);
    }
}

隨后,在初始化文件init.php中重新注冊(cè)DI()->notorm即可,如:

//數(shù)據(jù)操作 - 基于NotORM,$_GET['__sql__']可自行改名
DI()->notorm = function() {
    $debug = !empty($_GET['__sql__']) ? true : false;
    return new Common_MyDB(DI()->config->get('dbs'), $debug);
};

1.15.3 可選的Model基類(lèi)

(1)表數(shù)據(jù)入口模式

我們一直在考慮,是否應(yīng)該提供數(shù)據(jù)庫(kù)的基本操作支持,以減少開(kāi)發(fā)人員重復(fù)手工編寫(xiě)基本的數(shù)據(jù)操作。

最后,我們認(rèn)為是需要的。然后就引發(fā)了新的問(wèn)題:是以繼承還是以委托來(lái)支持?

委托有助于降低繼承的層級(jí),但仍然需要編寫(xiě)同類(lèi)的操作然后再次委托。所以,這里提供了基于NotORM的Model基類(lèi):PhalApi_Model_NotORM。

然而提供這個(gè)基類(lèi)還是會(huì)遇到一些問(wèn)題,例如:如何界定基本操作?如何處理分表存儲(chǔ)?如何支持定制化?

由于我們這里的Model使用了 “表數(shù)據(jù)入口” 模式,而不是“行數(shù)據(jù)入口”,也不是“活動(dòng)紀(jì)錄”,也不是復(fù)雜的“數(shù)據(jù)映射器”。所以在使用時(shí)可以考慮是否需要此基類(lèi)。即使這樣,你也可以很輕松轉(zhuǎn)換到“行數(shù)據(jù)入口”和“活動(dòng)紀(jì)錄”模式。這里,PhalApi中的Model是更廣義上的數(shù)據(jù)源層(后面會(huì)有更多說(shuō)明),因此對(duì)應(yīng)地PhalApi_Model_NotORM基類(lèi)充當(dāng)了數(shù)據(jù)庫(kù)表訪問(wèn)入口的對(duì)象,處理表中所有的行。

(2)規(guī)約層的CURD

在明白了Model基類(lèi)的背景后,再來(lái)了解其具體的操作和如何繼承會(huì)更有意義。

而具體的操作則與數(shù)據(jù)表的結(jié)構(gòu)相關(guān),在“約定編程”下:即每一個(gè)表都有一個(gè)主鍵(通常為id,也可以自由配置)以及一個(gè)序列化LOB字段ext_data。我們很容易想到Model接口的定義(注釋已移除,感興趣的同學(xué)可查看源碼):

interface PhalApi_Model {

    public function get($id, $fields = '*');

    public function insert($data, $id = NULL);

    public function update($id, $data);

    public function delete($id);
}

上面的接口在規(guī)約層上提供了基于表主鍵的CURD基本操作,在具體實(shí)現(xiàn)時(shí),需要注意兩點(diǎn):一是分表的處理;另一點(diǎn)則是LOB字段的序列化。

(3)不使用Model基類(lèi)的寫(xiě)法

由于我們使用了NotORM進(jìn)行數(shù)據(jù)庫(kù)的操作,所以這里也提供了基于NotORM的基類(lèi):PhalApi_Model_NotORM。下面以我們熟悉的獲取用戶(hù)的基本信息為例,說(shuō)明此基類(lèi)的使用。

為喚醒記憶,下面貼上Model_User類(lèi)原來(lái)的代碼:

// $ vim ./Demo/Model/User.php

<?php

class Model_User {

    public function getByUserId($userId) {
        return DI()->notorm->user->select('*')->where('id = ?', $userId)->fetch();
    }
}

對(duì)應(yīng)的調(diào)用:

$model = new Model_User();
$rs = $model->getByUserId($userId);

(4)繼承Model基類(lèi)的寫(xiě)法

若繼承于PhalApi_Model_NotORM,則是:

// $ vim ./Demo/Model/User.php

<?php

class Model_User extends PhalApi_Model_NotORM {

    protected function getTableName($id) {
        return 'user';
    }
}

從上面的代碼可以看出,基類(lèi)已經(jīng)提供了基于主鍵的CURD操作,但我們需要鉤子函數(shù)以返回對(duì)應(yīng)的表名。相應(yīng)地,外部調(diào)用則調(diào)整為:

$model = new Model_User();
$rs = $model->get($userId);

再進(jìn)一步,我們可以得到其他的基本操作:

$model = new Model_User();

//查詢(xún)
$row = $model->get(1);
$row = $model->get(1, 'id, name'); //取指定的字段
$row = $model->get(1, array('id', 'name')); //可以數(shù)組取指定要獲取的字段

//更新
$data = array('name' => 'test', 'update_time' => time());
$model->update(1, $data); //基于主鍵的快速更新

//插入
$data = array('name' => 'phalapi');
$id = $model->insert($data);
//$id = $model->insert($data, 5); //如果是分表,可以這樣指定

//刪除
$model->delete(1);

1.15.4 定制化你的Model基類(lèi)

正如上面提及到的兩個(gè)問(wèn)題:LOB序列化和分表處理。所以,如果PhalApi現(xiàn)有就此兩問(wèn)題的解決方案不能滿(mǎn)足項(xiàng)目的需求,可作定制化處理。

(1)LOB序列化

先是LOB序列化,考慮到有分表的存在,當(dāng)發(fā)生數(shù)據(jù)庫(kù)變更時(shí)(特別在線(xiàn)上環(huán)境)會(huì)有一定的難度和風(fēng)險(xiǎn),因此引入了擴(kuò)展字段ext_data。當(dāng)然,此字段也應(yīng)對(duì)數(shù)據(jù)庫(kù)變更的同時(shí),也可以作為簡(jiǎn)單明了的值對(duì)象的大對(duì)象。序列化LOB首先要考慮的問(wèn)題是使用二進(jìn)制(BLOB)還是文本(CLOB),出于通用性、易讀性和測(cè)試性,我們目前使用了json格式的文本序列化。所以,如果考慮到空間或性能問(wèn)題(在少量數(shù)據(jù)下我認(rèn)為問(wèn)題不大,如果數(shù)據(jù)量大,應(yīng)該及時(shí)重新調(diào)整數(shù)據(jù)庫(kù)表結(jié)構(gòu)),可以重寫(xiě)formatExtData() & parseExtData()。

如改成serialize序列化:

abstract class Common_Model_NotORM extends PhalApi_Model_NotORM {

    /**
     * 對(duì)LOB的ext_data字段進(jìn)行格式化(序列化)
     */
    protected function formatExtData(&$data) {
        if (isset($data['ext_data'])) {
            $data['ext_data'] = serialize($data['ext_data']);
        }
    }

    /**
     * 對(duì)LOB的ext_data字段進(jìn)行解析(反序列化)
     */
    protected function parseExtData(&$data) {
        if (isset($data['ext_data'])) {
            $data['ext_data'] = unserialize($data['ext_data'], true);
        }
    }

    // ...
}

將Model類(lèi)繼承于Common_Model_NotORM后,

// $ vim ./Demo/Model/User.php

<?php
class Model_User extends Common_Model_NotORM {
   //...
}

就可以輕松切換到序列化,如:

$model = new Model_User();

//帶有ext_data的更新
$extData = array('level' => 3, 'coins' => 256);
$data = array('name' => 'test', 'update_time' => time(), 'ext_data' => $extData);
$model->update(1, $data); //基于主鍵的快速更新

(2)分表處理

其次是分表處理,同樣考慮到分表的情況,以及不同的表可能配置不同的主鍵表,而基于主鍵的CURD又必須要先知道表的主鍵名才能進(jìn)行SQL查詢(xún)。所以,問(wèn)題就演變成了如何找到表的主鍵名。這里可以自動(dòng)匹配,也可以手工指定。自動(dòng)匹配是智能的,因?yàn)楫?dāng)我們更改表的主鍵時(shí),可以自動(dòng)同步更新而不需要擔(dān)心遺漏(雖然這種情況很少發(fā)生)。手工指定可以大大減少系統(tǒng)不必要的匹配操作,因?yàn)槲覀冮_(kāi)發(fā)人員也知道數(shù)據(jù)庫(kù)的主鍵名是什么,但需要手工編寫(xiě)一些代碼。在這里,提供了可選的手工指定,即可重寫(xiě)getTableKey($table)來(lái)指定你的主鍵名。

如,當(dāng)我們的表的主鍵都固定為id時(shí):

abstract class Common_Model_NotORM extends PhalApi_Model_NotORM {

    protected function getTableKey($table) {
        return 'id';
    }
}

以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)