2016-05-15 73 views
0

我在Web開發類。他們教我們用PDO連接到MySQL數據庫,然後在一個類中創建一些方法來訪問PDO連接。PDO MySQL`prepared statements`使用或不使用佔位符

db_model.php

<?php 
class DB { 
    protected $db; 
    function __construct() { 
     $this->db = new PDO("mysql:host=localhost;dbname=blog", "root", ""); 
    } 

    function executeQuery($query) { 
     $statement = $this->db->prepare($query);  
     $statement->execute(); 
     return $statement; 
    } 
} 

articles_model.php

<?php 
require_once "db_model.php"; 

class ArticlesModel extends DB { 
    function getAll() { 
     $statement = $this->executeQuery("SELECT * FROM articles"); 
     return $statement->fetchAll(PDO::FETCH_ASSOC); 
    } 

    function getArticle($id) { 
     $statement = $this->executeQuery("SELECT * FROM articles WHERE id = " . $id); 
     return $statement->fetchAll(PDO::FETCH_ASSOC); 
    } 

    function insertArticle($article) { 
     $this->executeQuery("INSERT into articles (title, body, image) values ('".$article["title"]."', '".$article["body"]."', '".$article["file"]."');"); 
     return $this->db->lastInsertId(); 
    } 

    function updateArticle($article) { 
     $statement = $this->executeQuery("UPDATE articles SET title ='".$article["title"]."',body = '".$article["body"]."' WHERE id =".$article["id"]); 
     return $statement->rowCount();  
    } 

    function deleteArticle($article) { 
     $statement = $this->executeQuery("DELETE FROM articles WHERE id =".$article["id"]); 
     return $statement->rowCount(); 
    } 
} 

我從一個先進的PHP程序員,但就像我知道的很遠的是,好的做法是使用真正的準備帶有佔位符的語句不僅在SQL語句中連接PHP變量,所以我帶着這個:

db_model.php

<?php 

define('DB_NAME', 'blog'); 
define('DB_HOST', 'localhost'); 
define('DB_USER', 'root'); 
define('DB_PASS', ''); 
define('DB_CHAR', 'utf8'); 

class DB { 
     protected $db; 
     function __construct() { 
       $opt = array(
         PDO::ATTR_ERRMODE   => PDO::ERRMODE_EXCEPTION, 
         PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, 
         PDO::ATTR_EMULATE_PREPARES => TRUE 
       ); 
       $dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset='.DB_CHAR; 
       $this->db = new PDO($dsn, DB_USER, DB_PASS, $opt); 
     } 

     function executeQuery($query) { 
       $statement = $this->db->prepare($query); 
       $statement->execute(); 
       return $statement; 
     } 
} 

articles_model.php

<?php 

require_once 'db_model.php'; 

class ArticlesModel extends DB { 
     function getAll() { 
       $statement = $this->executeQuery('SELECT * FROM articles'); 
       return $statement->fetchAll(PDO::FETCH_ASSOC); 
     } 

     function getArticle($id) { 
       $statement = $this->executeQuery('SELECT * FROM articles WHERE id = :id'); 
       $statement->bindParam(':id', $id, PDO::PARAM_INT); 
       return $statement->fetchAll(PDO::FETCH_ASSOC); 
     } 

     function insertArticle($article) { 
       $statement = $this->executeQuery('INSERT into articles (title, body, image) values (:title, :body, :image)'); 
       $statement->bindParam(':title', $article['title'], PDO::PARAM_VAR); 
       $statement->bindParam(':body', $article['body'], PDO::PARAM_VAR); 
       $statement->bindParam(':image', $article['file'], PDO::PARAM_VAR); 
       return $statement->lastInsertId(); 
     } 

     function updateArticle($article) { 
       $statement = $this->executeQuery('UPDATE articles SET title = :title, body = :body WHERE id = :id'); 
       $statement->bindParam(':title', $article['title'], PDO::PARAM_VAR); 
       $statement->bindParam(':body', $article['body'], PDO::PARAM_VAR); 
       $statement->bindParam(':id', $article['id'], PDO::PARAM_INT); 
       return $statement->fetchColumn(); 
     } 

     function deleteArticle($article) { 
       $statement = $this->executeQuery('DELETE FROM articles WHERE id = :id'); 
       $statement->bindParam(':id', $article['id'], PDO::PARAM_INT); 
       return $statement->fetchColumn(); 
     } 
} 

哪種方法更安全/更正確使用?我錯了嗎?順便說一句,我本可以使用更乾淨的代碼,但希望儘可能使我的代碼儘可能靠近教師的代碼。 (例如,不使用bindparam()無處不在,但execute(array())

編輯:

我認爲正確的應該是:

<?php 

require_once 'db_model.php'; 

class ArticlesModel extends DB { 
     function getAll() { 
       $statement = $this->executeQuery('SELECT * FROM articles'); 
       return $statement->fetchAll(PDO::FETCH_ASSOC); 
     } 

     function getArticle($id) { 
       $statement = $this->executeQuery('SELECT * FROM articles WHERE id = :id'); 
       $statement->bindParam(':id', $id, PDO::PARAM_INT); 
       return $statement->fetchAll(PDO::FETCH_ASSOC); 
     } 

     function insertArticle($article) { 
       $params = [ 
         ':title' => $article['title'], 
         ':body' => $article['body'], 
         ':image' => $article['file'] 
       ]; 
       $statement = $this->executeQuery('INSERT into articles (title, body, image) values (:title, :body, :image)', $params); 
       return $statement->lastInsertId(); 
     } 

     function updateArticle($article) { 
       $params = [ 
         ':title' => $article['title'], 
         ':body' => $article['body'], 
         ':id' => $article['id'] 
       ]; 
       $statement = $this->executeQuery('UPDATE articles SET title = :title, body = :body WHERE id = :id', $params); 
       return $statement->fetchColumn(); 
     } 

     function deleteArticle($article) { 
       $params = [':id' => $article['id']]; 
       $statement = $this->executeQuery('DELETE FROM articles WHERE id = :id', $params); 
       return $statement->fetchColumn(); 
     } 
} 
+1

在'ArticlesModel'類的所有方法中,首先將查詢發送到'executeQuery()'方法,然後綁定參數,這是錯誤的。仔細觀察,您首先準備好查詢,然後在綁定參數之前立即執行查詢。正確的順序是**準備**,**綁定**和*然後** **執行**。 –

+0

你是對的,我將不得不將參數作爲參數發送並妥善綁定,我忘了這一點,我不想改變我老師的方法。 – bsteo

+0

上面的代碼不適用於您的老師有缺陷的方法。 –

回答

0

雖然它是迄今爲止安全使用準備好的語句,從中真正受益當它們應用於SQL語句中的用戶輸入時,會保護您的代碼免受SQL注入攻擊。當你直接在你的SQL語句中輸入值時,這些好處不會被實現,因此準備好的語句不是必須的。您仍然可以從重新使用查詢中受益,但是,這是預先準備好的語句的另一個好處。

這就是說,整個過程使用統一的方法是一個很好的編程習慣,並且隨時使用預準備語句將有助於防止二階SQL注入攻擊。

相關問題