hi 昨天又213了,雖然有室友3點(diǎn)多才睡覺的客觀影響,但是昨晚不想學(xué)東西是本質(zhì)原因。今天搞起。打算3、4天之內(nèi),學(xué)完P(guān)DO和Ajax這兩個(gè),還望大家沒事兒來罵罵我,免的我又偷懶。 1、PDO 二、PDO對象的使用(二) 2.2 錯(cuò)誤信息 errorCode()錯(cuò)誤號; errorInfo(
hi
昨天又213了,雖然有室友3點(diǎn)多才睡覺的客觀影響,但是昨晚不想學(xué)東西是本質(zhì)原因。今天搞起。打算3、4天之內(nèi),學(xué)完P(guān)DO和Ajax這兩個(gè),還望大家沒事兒來罵罵我,免的我又偷懶。
1、PDO
二、PDO對象的使用(二)
2.2 錯(cuò)誤信息
errorCode()——錯(cuò)誤號;
errorInfo()——錯(cuò)誤信息;
舉個(gè)栗子
/*
* PDO錯(cuò)誤信息
*/
$pdo=new PDO('MySQL:host=localhost;dbname=imooc','root','');
$pdo->exec('use imooc_pdo');
$resultd=$pdo->exec('delete from user where id=13');
var_dump($resultd);
$insert='insert user(username,passWord,email) values("Knga","'.md5('king').'","shit@shit.com")';
$result1=$pdo->exec($insert);
var_dump($result1);
if ($result1==false) {
echo "出錯(cuò)了";
echo $pdo->errorCode();
PRint_r($pdo->errorInfo());
}
看一下錯(cuò)誤信息
Array ( [0] => 23000 [1] => 1062 [2] => Duplicata du champ 'Knga' pour la clef 'username' )
0為錯(cuò)誤類型,1062是代碼,2是錯(cuò)誤信息;(這里是由于username設(shè)置為了unique鍵,但是id號是還在增長的其實(shí))。
2.3 query()實(shí)現(xiàn)查詢
執(zhí)行一條語句,返回一個(gè)PDOstatement對象。
--舉個(gè)栗子
/*
* PDOquery
*/
$pdo=new PDO('mysql:host=localhost;dbname=imooc','root','');
$pdo->exec('use imooc_pdo');
$insert='select * from user';
$result1=$pdo->query($insert);
var_dump($result1); ?//查看statement對象
foreach ($result1 as $row){ ?//查看輸出結(jié)果(根據(jù)返回情況)
print_r($row);
}
if ($result1==false) {
echo "出錯(cuò)了";
echo $pdo->errorCode();
print_r($pdo->errorInfo());
}
如果sql語句有問題的話,statement對象是false,然后后面的輸出也是錯(cuò)誤信息;
如果sql語句正確,但查詢的內(nèi)容是不存在的,那么statement對象沒問題,然后輸出為空。
當(dāng)然這樣會好看一些:
foreach ($result1 as $row){ //查看輸出結(jié)果(根據(jù)返回情況)
// print_r($row);echo "
";
echo '編號:'.$row['id'];echo "
";
echo '用戶名:'.$row['username'];echo "
";
echo '密碼:'.$row['password'];echo "
";
echo '郵箱:'.$row['email'];echo "
";
echo "
";
}
當(dāng)然,query執(zhí)行增刪改都是沒問題的。
2.4 prepare()和execute()方法實(shí)現(xiàn)查詢
推薦使用的查詢方法,可以實(shí)現(xiàn)條件查詢。
prepare()——準(zhǔn)備要執(zhí)行的SQL語句,返回PDOstatement對象;
execute()——執(zhí)行一條預(yù)處理語句,返回true或false;
所以上面是一對。
--舉個(gè)例子
/*
* PDOprepare&execute方法
*/
$pdo=new PDO('mysql:host=localhost;dbname=imooc','root','');
$pdo->exec('use imooc_pdo');
$insert='select * from user where username="king"';
$result=$pdo->prepare($insert);
var_dump($result);
$result1=$result->execute();//執(zhí)行是對預(yù)處理語句
var_dump($result1);
print_r($result->fetchAll());//對statement對象才能有結(jié)果輸出
?
if ($result1==false) {
echo "出錯(cuò)了";
echo $pdo->errorCode();
print_r($pdo->errorInfo());
}
這里要小心預(yù)處理這種特殊情況,分清楚對象到底是誰就好辦了。
--選取輸出形式
要關(guān)聯(lián)數(shù)組輸出或者全部或者索引數(shù)組,有參數(shù)和方法兩種不同的方法。
header('content-type:text/html;charset=utf-8');
try{
$pdo=new PDO('mysql:host=localhost;dbname=imooc','root','root');
$sql='select * from user';
$stmt=$pdo->prepare($sql);
$res=$stmt->execute();
// if($res){
// while($row=$stmt->fetch(PDO::FETCH_ASSOC)){//僅需要關(guān)聯(lián)數(shù)組輸出
// print_r($row);
// echo '
';
// }
// }
// $rows=$stmt->fetchAll(PDO::FETCH_ASSOC);
// print_r($rows);
echo '
';
$stmt->setFetchMode(PDO::FETCH_ASSOC); //同樣的實(shí)現(xiàn)效果,用這個(gè)方法也可以,設(shè)置默認(rèn)模式
//var_dump($stmt);
$rows=$stmt->fetchAll();
print_r($rows);
}catch(PDOException $e){
echo $e->getMessage();
}
一般的我們都是想要索引數(shù)組的。
2.5 設(shè)置數(shù)據(jù)庫連接屬性
setAttribute()——設(shè)置數(shù)據(jù)庫連接屬性;
getAttribute()——得到數(shù)據(jù)庫連接屬性;
--舉個(gè)例子
$pdo=new PDO('mysql:host=localhost;dbname=imooc','root','');
echo "自動提交".$pdo->getAttribute(PDO::ATTR_AUTOCOMMIT);echo "
";
//記住pdo是個(gè)對象,所以得到屬性,你懂的。然后它內(nèi)部是有很多設(shè)定好的屬性值的,這就是我們得到屬性的前提。
echo "默認(rèn)的錯(cuò)誤處理模式:".$pdo->getAttribute(PDO::ATTR_ERRMODE);echo "
";
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 0);
echo "自動提交".$pdo->getAttribute(PDO::ATTR_AUTOCOMMIT);echo "
";
然后試著得到一大波屬性信息:
$attrArr=array(
'AUTOCOMMIT','ERRMODE','CASE','PERSISTENT','SERVER_INFO','SERVER_VERSION'
);
foreach ($attrArr as $attr){
echo "PDO::ATTR_$attr: ";
echo $pdo->getAttribute(constant("PDO::ATTR_$attr"))."
";
}
有些是沒有的,會有錯(cuò)誤信息,沒什么關(guān)系。
?
三、PDOstatement對象的使用
3.1 quote()方法防止SQL注入
--SQL注入
首先舉個(gè)例子說明這個(gè)簡單的SQL注入(其實(shí)我也不是很懂——百度一下http://baike.baidu.com/link?url=jiMtgmTeePlWAqdAntWbk-wB8XKP8xS3ZOViJE9IVSToLP_iT2anuUaPdMEM0b-VDknjolQ8BdxN8ycNLohup_)
所謂SQL注入,就是通過把SQL命令插入到Web表單提交或輸入域名或頁面請求的查詢字符串,最終達(dá)到欺騙服務(wù)器執(zhí)行惡意的SQL命令。
所以也就是要有表單,然后需要跟數(shù)據(jù)庫進(jìn)行查詢數(shù)據(jù)等等,然后通過惡意的運(yùn)用規(guī)則上的漏洞,得到大量的,而不是頁面所希望的數(shù)據(jù)。栗子如下:
例子為登錄的情況——登錄需要有用戶名密碼等,需要與數(shù)據(jù)庫中的信息進(jìn)行比對;
首先是登錄頁面
$stmt=$pdo->query($sql);
echo $stmt->rowCount();//顯示結(jié)果集statement對象中的行數(shù)
} catch (PDOException $e) {
echo $e->getMessage();
}
然后瀏覽器中打開login.html,輸入數(shù)據(jù)庫中有的username和password,點(diǎn)擊登陸,會得到1;
若輸入錯(cuò)誤的信息,一般會得到0;
注意,若輸入諸如用戶名為'or 1=1#,密碼隨意,就會輕松得到數(shù)據(jù)庫的所有數(shù)據(jù)。這是由于sql語句本身的規(guī)則造成的。
所以需要過濾用戶輸入的信息,不要相信用戶的所有操作。
--應(yīng)對方法
echo $pdo->quote($username);
寫這么一句,再用上述的作弊代碼,輸出會多出單引號,以及自動加上\:
?'\'or 1=1#'
但這么做的話,$username的調(diào)用,會自動加上引號,所以下面的sql語句就要跟著變動:
$username=$pdo->quote($username);
$pdo->exec('use imooc_pdo');
$sql="select * from user where username={$username} and password='{$password}'";
簡單的說就是把用戶名上個(gè)套,對于有數(shù)據(jù)庫的情況,似乎都要防這個(gè)。
但是不建議使用這種手段——建議使用prepare+execute的預(yù)處理手段。
3.2 預(yù)處理語句中占位符的使用
很好的防止注入;而且一次編譯即可,多次執(zhí)行,減小系統(tǒng)的開銷;
--占位符:(命名參數(shù))(推薦)
header('content-type:text/html;charset=utf-8');
$username=$_POST['username'];
$password=$_POST['password'];
try {
$pdo=new PDO('mysql:host=localhost;dbname=imooc','root','');
$pdo->exec('use imooc_pdo');
$sql="select * from user where username=:username and password=:$password";
$stmt=$pdo->prepare($sql);
$stmt->execute(array(":username"=>$username,":password"=>$password));
//$stmt=$pdo->query($sql);
echo $stmt->rowCount();//顯示結(jié)果集statement對象中的行數(shù)
} catch (PDOException $e) {
echo $e->getMessage();
}
對應(yīng)的sql語句,對應(yīng)的執(zhí)行,需要傳遞的參數(shù)也要對應(yīng)的上。
--占位符?
$sql="select * from user where username=? and password=?";
$stmt=$pdo->prepare($sql);
$stmt->execute(array($username,$password));
感覺?方式要簡單一點(diǎn),就三個(gè)點(diǎn)——sql語句中輸入占位符+預(yù)處理+執(zhí)行(傳遞多個(gè)數(shù)據(jù)用array)。
3.3 bindParam()方法綁定參數(shù)
把一個(gè)參數(shù)綁定到變量名。?
/*
* 綁定參數(shù)
*/
header('content-type:text/html;charset=utf-8');
try {
$pdo=new PDO('mysql:host=localhost;dbname=imooc','root','');
$pdo->exec('use imooc_pdo');
$sql="insert user(username,password,email) values(:username,:password,:email)";
$stmt=$pdo->prepare($sql);
$username="Wid";$password="123";$email="324@QQ.com"; //定義參數(shù)
$stmt->bindParam(":username", $username,PDO::PARAM_STR);
$stmt->bindParam(":password",$password);
$stmt->bindParam(":email",$email);
$stmt->execute();
$res=$pdo->query("select * from user");
foreach ($res as $row){ //查看輸出結(jié)果(根據(jù)返回情況)
// print_r($row);echo "
";
echo '編號:'.$row['id'];echo "
";
echo '用戶名:'.$row['username'];echo "
";
echo '密碼:'.$row['password'];echo "
";
echo '郵箱:'.$row['email'];echo "
";
echo "
";
}
} catch (PDOException $e) {
echo $e->getMessage();
}
其實(shí)就是為了不用每次更改sql語句來執(zhí)行略重復(fù)的操作。?
當(dāng)然還可以換個(gè)占位符
// $sql="insert user(username,password,email) values(?,?,?)";
// $stmt->bindParam(1,$username);
所以,總之,實(shí)際上:占位符會比較清楚,?會混淆。
3.4 bindValue()實(shí)現(xiàn)綁定參數(shù)
把值綁定到參數(shù)中。
/*
* 綁定參數(shù)
*/
header('content-type:text/html;charset=utf-8');
try {
$pdo=new PDO('mysql:host=localhost;dbname=imooc','root','');
$pdo->exec('use imooc_pdo');
$sql="insert user(username,password,email) values(:username,:password,:email)";
// $sql="insert user(username,password,email) values(?,?,?)";
$stmt=$pdo->prepare($sql);
//假設(shè)email參數(shù)不變
$stmt->bindValue(":email", 'shit@shit.com');
$username="Wade";$password="123";
$stmt->bindParam(":username", $username,PDO::PARAM_STR);
$stmt->bindParam(":password",$password);
$stmt->execute();
$res=$pdo->query("select * from user");
foreach ($res as $row){ //查看輸出結(jié)果(根據(jù)返回情況)
// print_r($row);echo "
";
echo '編號:'.$row['id'];echo "
";
echo '用戶名:'.$row['username'];echo "
";
echo '密碼:'.$row['password'];echo "
";
echo '郵箱:'.$row['email'];echo "
";
echo "
";
}
} catch (PDOException $e) {
echo $e->getMessage();
}
應(yīng)用場景就是當(dāng)某個(gè)值固定不變的時(shí)候,就可以固定變量的參數(shù)值。
3.5 bindColumn()方法綁定參數(shù)
將綁定一列到php對象。
$pdo=new PDO('mysql:host=localhost;dbname=imooc','root','');
$pdo->exec('use imooc_pdo');
$sql="select * from user";
$stmt=$pdo->prepare($sql);
$stmt->execute();
//控制輸出
$stmt->bindColumn(2, $username);
$stmt->bindColumn(3,$password);
$stmt->bindColumn(4,$email);
while ($stmt->fetch(PDO::FETCH_BOUND)){
echo '用戶名:'.$username.'-密碼:'.$password.'-郵箱:'.$email.'
';
}
這里的用法就是對輸出結(jié)果進(jìn)行控制,利于輸出格式的調(diào)控。
當(dāng)然,可以看看結(jié)果集中到底有幾列,然后每一列是什么:
echo '結(jié)果集中的列數(shù):'.$stmt->columnCount().'
';
print_r($stmt->getColumnMeta(2));
3.6 fetchColumn()從結(jié)果集中取一列
上述的getColumnMeta()方法實(shí)際上在PHP該版本中是個(gè)實(shí)驗(yàn)的函數(shù),可能會在將來的版本中消失。
$stmt->execute();
print_r($stmt->fetchColumn(3));
需要注意該方法很蛋疼的地方在于會每執(zhí)行一次,指針向下一位,所以只需要指定第幾列,但并不知道在哪一行。
3.7 debugDumpParams()打印一條預(yù)處理語句
在bindParam中測試這個(gè)方法:
$stmt->debugDumpParams();
結(jié)果是一大堆:
SQL: [71] insert user(username,password,email) values(:username,:password,:email) Params: 3 Key: Name: [9] :username paramno=-1 name=[9] ":username" is_param=1 param_type=2 Key: Name: [9] :password paramno=-1 name=[9] ":password" is_param=1 param_type=2 Key: Name: [6] :email paramno=-1 name=[6] ":email" is_param=1 param_type=2
也就是說會給出預(yù)處理時(shí)的詳細(xì)情況。
很明顯就是為了Debug而生的方法。
3.8 nextRowset()方法取出所有結(jié)果集
用于比如,mysql的存儲過程(看我之前mysql的博文就有),一下子取出很多結(jié)果集,然后對集進(jìn)行操作。
實(shí)際上是指針一步步下移就好了。
例子我懶了,不想敲了。。。。
?
雖然沒寫很多,就這樣吧。
過兩天想去復(fù)查一下腳,雖然還在痛,不知道還敢不敢活血了。。。。
?

熱AI工具

Undress AI Tool
免費(fèi)脫衣圖片

Undresser.AI Undress
人工智慧驅(qū)動的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強(qiáng)大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6
視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)
