2016-05-14 136 views
0

我正在開發Web課程。用PHP PDO MySQL的工作,他們教給我們上了一次研討會,做到這一點:PHP PDO MySQL count()準備語句

function countUsers($search) { 
    $and = ''; 
    if ($search != '') { 
     $and = " AND user_name LIKE '%".$search."%'";  
    } 
    $total = $this->db->query("SELECT COUNT(id) as rows FROM users WHERE valid = 1" . $and)->fetch(PDO::FETCH_OBJ); 
    return $total->rows; 
} 

從我的角度來看,這是完全錯誤的,語句不備,並直接從用戶輸入傳遞沒有任何驗證,可導致SQL注入,所以我提出這個訓練師(我知道fetchColumn()會更適合這裏,但我們堅持這個爲例子來說):

function countUsers($search) { 
    $and = ''; 
    $sqlSearch = "%$search%"; 

    if ($search != '') { 
     $and = " AND user_name LIKE :username"; 
    } 

    $sql = "SELECT COUNT(id) as rows FROM users WHERE valid = 1" . $and; 
    $sth = $this->db->prepare($sql); 
    if ($search != '') { 
     $sth->bindParam(':username', $sqlSearch, PDO::PARAM_STR); 
    } 
    $sth->execute(); 
    $total = $sth->fetch(PDO::FETCH_OBJ); 
    return $total->rows; 
} 

難道我錯了嗎?他們是錯的還是我們都錯了?

+3

你應該總是綁定不受信任的參數(這幾乎是所有的參數)。 – JimL

+2

你是完全正確的。即使輸入是可信的,它仍然可以包含破壞sql的字符,所以您應該始終使用預準備語句並將值綁定到佔位符。 – jeroen

+0

我在課堂上提出了這個問題,他們說我是對的,但這不是問題,因爲這只是一個工作示例,並不是課程的目的,有20個小時的網絡安全。我認爲他們是非常錯誤的,給學生完全錯誤和不安全的例子。如果不利用PDO的「準備語句」,他們更好地使用「mysql_ *」或「mysqli_ *」。 – bsteo

回答

4

是的你是對的。

但是,您的代碼不是最優的。事實上,準備好的陳述旨在使您的代碼更清潔,而不是更臃腫。清理我做的

function countUsers($search) { 
    $sql = "SELECT COUNT(id) FROM users WHERE valid = 1 AND user_name LIKE ?"; 
    $sth = $this->db->prepare($sql); 
    $sth->execute(["%$search%"]); 
    return $sth->fetchColumn(); 
} 

部分僅僅是一種技巧 - 因爲你可以隨時搜索LIKE '%%'和匹配所有行(不包括那些其中user_name是空雖然)。

但剩下的只是正確使用PDO的特點:

  • 你總是可以使用位置佔位符
  • 你可以隨時避免bindParam()調用
  • 你應該用適當的抓取模式
+1

它應該是一個數組參數:' - > execute(「%$ search%」);' – hjpotter92

+0

是的,我知道,我只是讓我的教練的例子少了一些錯誤。 – bsteo

+0

@你的常識,你的'唯一正確的PDO指南'讓我對正確使用PDO非常關鍵:) – bsteo