W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
在 Joomla 4 中, Joomla 數(shù)據(jù)庫查詢轉(zhuǎn)變?yōu)槭褂妙A(yù)編譯語句,本文旨在闡明我們這樣做的原因和方式。
簡單的來說,預(yù)編譯語句相比之前的字符串查詢語句將會有兩大優(yōu)勢:
通常我們的一條sql在db接收到最終執(zhí)行完畢返回可以分為下面三個過程:
我們把這種普通語句稱作Immediate Statements。
但是很多情況,我們的一條sql語句可能會反復(fù)執(zhí)行,或者每次執(zhí)行的時候只有個別的值不同(比如query的where子句值不同,update的set子句值不同,insert的values值不同)。如果每次都需要經(jīng)過上面的詞法語義解析、語句優(yōu)化、制定執(zhí)行計劃等,則效率就明顯不行了。
所謂預(yù)編譯語句就是將這類語句中的值用占位符替代,可以視為將sql語句模板化或者說參數(shù)化,一般稱這類語句叫Prepared Statements或者Parameterized Statements 。
預(yù)編譯語句的優(yōu)勢歸納為:一次編譯、多次運行,省去了解析優(yōu)化等過程;此外預(yù)編譯語句能防止sql注入。
joomla在底層的JDatabaseDriver類中已經(jīng)幫我們實現(xiàn)好了預(yù)編譯語句這項功能,開發(fā)者只需要在寫查詢語句的時候調(diào)用即可。以下面的查詢語句為例:
正常的SQL語句寫法:
$query =$this->db->getQuery(true)
->select($this->db->quoteName(array('id','password')))
->from($this->db->quoteName('#__users'))
->where($this->db->quoteName('username') .'=' .$this->db->quote($credentials['username']));
轉(zhuǎn)換為預(yù)編譯語句的SQL語句寫法:
$query =$this->db->getQuery(true)
->select($this->db->quoteName(array('id','password')))
->from($this->db->quoteName('#__users'))
->where($this->db->quoteName('username') .' = :username')
->bind(':username',$credentials['username']);
通過在where中使用占位符,在bind中進行參數(shù)綁定就實現(xiàn)了預(yù)編譯的功能。另外,請注意最后的bind方法,在這里我們不再使用$db的quote(加引號)的方法,因為數(shù)據(jù)庫驅(qū)動將自動的幫我們加上。
JDatabaseDriver 會對一些函數(shù)自動使用預(yù)編譯語句,如 whereIn()和whereNotIn()方法將自動的使用。
典型的代碼如下:
$query =$this->db->getQuery(true)
->select($this->db->quoteName(array('id, password')))
->from($this->db->quoteName('#__users'))
->whereIn($this->db->quoteName('id'), [ 1, 2, 3 ]);
這個查詢將會轉(zhuǎn)換為預(yù)編譯語句的SQL如下:
SELECT
`id`, `password`
FROM
`#__users`
WHERE
`id`IN (
:preparedArray1,
:preparedArray2,
:preparedArray3
);
其中的占位符 :preparedArray1-3 將在執(zhí)行時填充 1,2,3。
通過在where中使用占位符,在bind中進行參數(shù)綁定就實現(xiàn)了預(yù)編譯的功能。另外,請注意最后的bind方法,在這里我們不再使用$db的quote(加引號)的方法,因為數(shù)據(jù)庫驅(qū)動將自動的幫我們加上。
另外,以下函數(shù)接受數(shù)組以減少函數(shù)調(diào)用開銷
另外在編程中使用預(yù)編譯的一個好處是可以方便的使用循環(huán),下面是一段實例代碼:
$listOfUsernames = ['admin','user1' ];
$query =$this->db->getQuery(true)
->select($this->db->quoteName(array('id','password')))
->from($this->db->quoteName('#__users'))
->where($this->db->quoteName('username') .' = :username')
->bind(':username',$username);
foreach($listOfUsernames as $name)
{
$username =$name;
$this->db->setQuery($query);
$user =$this->db->loadObject();
print_r($user);
}
在上面的循環(huán)中,給$username賦值,然后重新調(diào)用setQuery方法來獲得數(shù)據(jù),非常的方便。
同樣,也可以使用數(shù)據(jù)組來完成參數(shù)的綁定,代碼如下:
$query =$this->db->getQuery(true)
->select($this->db->quoteName(array('id','password')))
->from($this->db->quoteName('#__users'))
->where($this->db->quoteName('username') .' = :username')
->where($this->db->quoteName('id') .' = :id')
->bind([':username',':id'], [$credentials['username'], 42], [Joomla\Database\ParameterType::STRING, Joomla\Database\ParameterType::INTEGER]);
在上面的代碼中添加 username 和 id 作為綁定參數(shù),并為每個變量設(shè)置正確的 ParameterType。也可以對所有綁定值和 ParameterType 使用一個變量。 代碼如下:
$query =$this->db->getQuery(true)
->select($this->db->quoteName(array('id','password')))
->from($this->db->quoteName('#__users'))
->where($this->db->quoteName('username') .' = :username')
->where($this->db->quoteName('password') .' = :password')
->bind([':username',':password], $credentials['username']);
在上面參數(shù) :username 和 :password 設(shè)置為相同的值和默認的參數(shù)類型。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: