2013-01-03 71 views
4

我想基於URL參數中的數據(是的,我知道這很容易受到攻擊,但是它的內部代碼爲實用程序)使用PDO運行查詢。迭代PDO查詢的結果

$user = 'USER'; 
$pass = 'PASSWORD'; 
$dsn = 'mysql:dbname=PRODUCTS;host=HOST'; 

try { 
    $productDB = new PDO($dsn, $user, $pass); 
    $productDB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
} 
catch(PDOException $e) { 
    $msg = 'PDO ERROR' . $e->getFile() . ' L.' . $e->getLine() . ' : ' . $e->getMessage(); 
    die($msg); 
} 
if(isset($_GET['cat'])) 
{ 
    $cat = $_GET['cat']; 
    print "cat = $cat <br>"; 
    $products = $productDB->prepare('SELECT * FROM products WHERE cat_id LIKE ?'); 
    $products->execute(array($cat)); 
    $rows = $products->rowCount(); 
    print "$rows rows returned"; 
?> 
<table border="1"> 
<tr> 
    <td>product_id</td> 
    <td>product_name</td> 
</tr> 
<?php 
foreach ($products->fetchAll() as $row) { 
    $id = $row['product_id']; 
    $product_name = $row['product_name']; 
    print "<tr>"; 
    print "<th scope=\"row\"><b>$id</b></th>"; 
    print "<td> $product_name </td>"; 
    print "<tr>"; 
    } 
print "</table>"; 
} 
?> 

當我運行此代碼時,它根據查詢打印正確的行數,但不會填充表。

我也曾嘗試與更換prepareexecute線:

$products = $productDB->query("SELECT * FROM products WHERE cat_id LIKE $cat"); 

它返回正確的行數,但是不以其他方式幫助。

最後,我嘗試過的東西,如替換的foreach行:

$rows = $products->fetchAll(); 
foreach ($rows as $row) { 

我嘗試做相同的固定查詢所有的工作很好,但我有麻煩工作如何放置查詢中的變量元素,然後迭代結果。

+1

如果您在第一個示例中使用佔位符,則不應該容易受到[SQL注入漏洞](http://bobby-tables.com/)的影響。在你的第二個例子中,你在字符串中有'$ cat',你*很脆弱。不要這樣做。由於注入未轉義的數據而發生攻擊。使用佔位符將確保它能夠正確轉義,所以最好儘可能使用它,並且在極少數情況下,如果不能,請特別小心。 – tadman

回答

2

試試這個(如果我理解正確的):

$products = $productDB->prepare("SELECT * FROM products WHERE cat_id LIKE :cat"); 

// Now, you can either do this : 
$products->bindParam('cat', '%'.$cat.'%'); 
$products->execute(); 

// or you can call execute with an associative array of your parameterized query. 
$products->execute(array('cat' => '%'.$cat.'%')); 

// Then, get all the results like this : 
$rows = $products->fetchAll(); 
foreach ($rows as $row) { 
    // Do work here .. 
} 

// Or, like this : 
while ($row = $products->fetch(PDO::FETCH_ASSOC)) { 
    // Do work here .. 
} 

我本人來說更喜歡,同時,因爲你沒有在一個VAR獲取整個查詢,減少所需的存儲量。

我也推薦你使用FETCH_*參數來獲得你想要的那種數組。

順便說一下,您需要知道rowCount不應該用於計算SELECT返回的行。如php.net所示:

如果由關聯的PDOStatement執行的最後一條SQL語句是SELECT語句,則某些數據庫可能會返回該語句返回的行數。但是,不能保證所有數據庫的這種行爲,並且不應該依賴便攜式應用程序。

+0

對於參數化查詢,我想我需要使用'prepare'和'execute',否?當我像這樣運行它時,它不會超出'query'行。 我確實嘗試了在'foreach'之外放置'fetchAll()'的想法,但它似乎沒有什麼區別。 –

+0

Oups,對不起,我太快了!是的,就是這樣,你必須準備好你的請求。 –

+0

在那裏,我改進了我的答案;) –

3

你沒有做任何事情來存儲結果:

$products->execute(array($cat)); 

需要在一個變量去:

$result = $products->execute(array($cat)); 

然後,而不是調用$products->fetchAll(),使用$results->fetchAll()

foreach ($result->fetchAll() as $row) 

I發現使用$query變量(對於prepare等)更容易,然後將結果變爲類似$result$product的結果。使代碼更易於閱讀。

+0

我確信' - > execute()'方法沒有返回數據,它只是改變了PDO對象的狀態,並使它接受'fetchAll()'等。儘管如此,我確實嘗試過。在這種情況下,當使用' - > rowCount()'測試時,程序沒有指出'$ result'變量中存在任何行,所以我不確定這是我需要的。 –