當(dāng)前位置:首頁 > 芯聞號 > 充電吧
[導(dǎo)讀]首先看findOne的函數(shù)定義,該函數(shù)定義在BaseActiveRecord當(dāng)中return?static::findOne(['id'?=>?$id,?'status'?=>?self:

首先看findOne的函數(shù)定義,該函數(shù)定義在BaseActiveRecord當(dāng)中


return?static::findOne(['id'?=>?$id,?'status'?=>?self::STATUS_ACTIVE]);


findOne定義是:


public?static?function?findOne($condition)
{
?????return?static::findByCondition($condition)->one();
}


也就是說我們需要看一下findByCondition的函數(shù)的定義,該函數(shù)定義在BaseActiveRecord

protected?static?function?findByCondition($condition)
{
????$query?=?static::find();

????if?(!ArrayHelper::isAssociative($condition))?{
?????//?query?by?primary?key
???????$primaryKey?=?static::primaryKey();
???????if?(isset($primaryKey[0]))?{
??????????$condition?=?[$primaryKey[0]?=>?$condition];
????????}?else?{
??????????throw?new?InvalidConfigException('"'?.?get_called_class()?.?'"?must?have?a?primary?key.');
????????}
????}
????return?$query->andWhere($condition);
}


find函數(shù)的定義是在ActiveRecord類中定義的

public?static?function?find()
{?????
?????return?Yii::createObject(ActiveQuery::className(),?[get_called_class()]);
}


也就是說$query是一個(gè)ActiveQuery的對象,其需要傳入的參數(shù)是需要進(jìn)行查詢的類的名字"User"; 中間這一部分,先不要看,因?yàn)檫€沒時(shí)間看,直接看下面的一行addWhere該函數(shù)的定義是在Query類中

public?function?andWhere($condition,?$params?=?[])
{
????if?($this->where?===?null)?{
???????$this->where?=?$condition;
????}?else?{
???????$this->where?=?['and',?$this->where,?$condition];
????}
????$this->addParams($params);
????return?$this;
}


在這里僅僅是將傳入的參數(shù)$condition,付給ActiveQuery的where成員變量。到此findByCondition已經(jīng)執(zhí)行完成,開始執(zhí)行one函數(shù)。該函數(shù)定義在ActiveQuery類當(dāng)中

public?function?one($db?=?null)
{
????$row?=?parent::one($db);
????if?($row?!==?false)?{
????????$models?=?$this->populate([$row]);
????????return?reset($models)??:?null;
????}?else?{
????????return?null;
????}
}


首先調(diào)用父類Query的one函數(shù),該函數(shù)定義如下:

public?function?one($db?=?null)
{
????return?$this->createCommand($db)->queryOne();
}


這里就需要看一下createCommand函數(shù),該函數(shù)的定義是:

public?function?createCommand($db?=?null)
{
????if?($db?===?null)?{
????????$db?=?Yii::$app->getDb();
????}
????list?($sql,?$params)?=?$db->getQueryBuilder()->build($this);
????return?$db->createCommand($sql,?$params);
}

這里可以看到需要獲得數(shù)據(jù)庫鏈接配置,然后創(chuàng)建queryBuilder對象,并利用build模式構(gòu)建完整的sql語句

public?function?build($query,?$params?=?[])
{
???$query?=?$query->prepare($this);

???$params?=?empty($params)???$query->params?:?array_merge($params,?$query->params);

???$clauses?=?[
??????$this->buildSelect($query->select,?$params,?$query->distinct,?$query->selectOption),
??????$this->buildFrom($query->from,?$params),
??????$this->buildJoin($query->join,?$params),
??????$this->buildWhere($query->where,?$params),
??????$this->buildGroupBy($query->groupBy),
??????$this->buildHaving($query->having,?$params),
????];
????$sql?=?implode($this->separator,?array_filter($clauses));
????$sql?=?$this->buildOrderByAndLimit($sql,?$query->orderBy,?$query->limit,?$query->offset);
????if?(!empty($query->orderBy))?{
????????foreach?($query->orderBy?as?$expression)?{
????????if?($expression?instanceof?Expression)?{
??????????$params?=?array_merge($params,?$expression->params);??
????????????}
????????}
????}
????if?(!empty($query->groupBy))?{??
??????foreach?($query->groupBy?as?$expression)?{
?????????if?($expression?instanceof?Expression)?{
????????????$params?=?array_merge($params,?$expression->params);
????????????}
????????}
????}

????$union?=?$this->buildUnion($query->union,?$params);
????if?($union?!==?'')?{
????????$sql?=?"($sql){$this->separator}$union";
????}
????return?[$sql,?$params];?
}



好吧,看看這個(gè)吧!?。?這一部分使用了build模式,進(jìn)行創(chuàng)建整個(gè)sql語句下面的幾個(gè)函數(shù)就先不說了,因?yàn)檫@一部分就是分部分進(jìn)行構(gòu)建查詢語句,分部分構(gòu)建select ?from join ? where group having? 每個(gè)函數(shù)都構(gòu)建了一部分語句,最后各個(gè)部分語句形成了$clauses是由各部分語句的數(shù)組。最后返回$sql, $param的數(shù)組,得到$sql之后可以繼續(xù)執(zhí)行了,,接下來創(chuàng)建$command

return?$db->createCommand($sql,?$params);


public?function?createCommand($sql?=?null,?$params?=?[])
{
????/**?@var?Command?$command?*/
????$command?=?new?$this->commandClass([
?????'db'?=>?$this,
??????'sql'?=>?$sql,
????]);

????return?$command->bindValues($params);
}


bindValues函數(shù)如下:



public?function?bindValues($values)
{
????if?(empty($values))?{
?????return?$this;
????}

????$schema?=?$this->db->getSchema();
????foreach?($values?as?$name?=>?$value)?{
???????if?(is_array($value))?{
?????????$this->_pendingParams[$name]?=?$value;
?????????$this->params[$name]?=?$value[0];
???????}?else?{
?????????$type?=?$schema->getPdoType($value);
?????????$this->_pendingParams[$name]?=?[$value,?$type];
?????????$this->params[$name]?=?$value;
????????}
????}
????return?$this;
}

先認(rèn)為param是空的吧,這一路跟下來,腦袋都快炸了,接下來要執(zhí)行的是,yiidbcommand類的queryOne函數(shù)

public?function?queryOne($fetchMode?=?null)
{
????return?$this->queryInternal('fetch',?$fetchMode);
}

queryInternal函數(shù)定義

protected?function?queryInternal($method,?$fetchMode?=?null)
{
????$rawSql?=?$this->getRawSql();
????Yii::info($rawSql,?'yiidbCommand::query');
????if?($method?!==?'')?{
???????$info?=?$this->db->getQueryCacheInfo($this->queryCacheDuration,?$this->queryCacheDependency);
???????if?(is_array($info))?{
???????????/*?@var?$cache?yiicachingCache?*/
??????????$cache?=?$info[0];
??????????$cacheKey?=?[
??????????__CLASS__,
??????????$method,
??????????$fetchMode,
??????????$this->db->dsn,
??????????$this->db->username,
??????????$rawSql,?
????????????];
??????????$result?=?$cache->get($cacheKey);
??????????if?(is_array($result)?&&?isset($result[0]))?{
????????????????Yii::trace('Query?result?served?from?cache',?'yiidbCommand::query');
????????????????return?$result[0];
????????????}
????????}
????}

????$this->prepare(true);
????$token?=?$rawSql;
???try?{
???????Yii::beginProfile($token,?'yiidbCommand::query');
???????$this->pdoStatement->execute();
???????if?($method?===?'')?{
???????????$result?=?new?DataReader($this);
????????}?else?{
???????????if?($fetchMode?===?null)?{
??????????????$fetchMode?=?$this->fetchMode;
????????????}
???????????$result?=?call_user_func_array([$this->pdoStatement,?$method],?(array)?$fetchMode);
???????????$this->pdoStatement->closeCursor();
????????}
????????Yii::endProfile($token,?'yiidbCommand::query');
????}?catch?(Exception?$e)?{
????????Yii::endProfile($token,?'yiidbCommand::query');
????????throw?$this->db->getSchema()->convertException($e,?$rawSql);
????}

????if?(isset($cache,?$cacheKey,?$info))?{
????????$cache->set($cacheKey,?[$result],?$info[1],?$info[2]);
????????Yii::trace('Saved?query?result?in?cache',?'yiidbCommand::query');
????}
????return?$result;
}

這樣看來,就是講所有的查詢結(jié)果進(jìn)行返回,那么會(huì)有人問不是findOne嗎?在哪里進(jìn)行的取one操作呢?是在ActiveQuery的one操作中,父類得到所有的查詢結(jié)果,子類將查詢結(jié)果進(jìn)行reset操作,將第一行記錄返回
查詢總覽: 所有的都是這樣查詢的static::findOne(條件),findOne函數(shù)定義是在BaseActiveRecord類中定義的,因?yàn)楫?dāng)前使用的User類的父類是ActiveRecord而ActiveRecord的父類是BaseActiveRecord 在此調(diào)用的是findByCondition在該函數(shù)中獲得了ActiveQuery類的對象,同時(shí)傳入需要修改的類的名稱(需要調(diào)用該類的靜態(tài)函數(shù)tableName,獲得表名稱),并且在findByCondition中將條件數(shù)組轉(zhuǎn)成 String,方便繼續(xù)使用,繼續(xù)調(diào)用ActiveQuery的addWhere記錄下ActiveQuery的where條件,之后調(diào)用Query的one()函數(shù),在Query的one函數(shù)中創(chuàng)建了yiidbConnection類的對象,繼續(xù)調(diào)用該db對象的getQueryBuilder函數(shù),創(chuàng)建了一個(gè)QueryBuilder對象,然后在QUeryBuilder對象中進(jìn)行完整的sql構(gòu)造,將sql查詢語句中可能出現(xiàn)的各個(gè)子查詢都進(jìn)行分別處理,各部分處理結(jié)果得到一個(gè)字符串,將這部分字符串組成數(shù)組,在展開implode,合成一個(gè)sql語句,將生成的sql語句傳遞給由yiidbConnection創(chuàng)建的yiidbcommand對象,并進(jìn)行執(zhí)行queryOne函數(shù)該函數(shù)調(diào)用queryInternal并返回結(jié)果集,最后由ActiveQuery的one函數(shù)進(jìn)行reset操作,返回第一個(gè)結(jié)果記錄






本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動(dòng)力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉