2013-08-05 3 views
1

pdo의 function __constructprivate 또는 public으로 설정해야합니까? public으로 설정하면 취약점의 대상이됩니까? 여기PHP PDO : pdo의`function __construct`를`private` 또는`public`으로 설정해야합니까?

내 DB 클래스는,

class pdo_connection 
{ 
    public $connection; // handle of the db connexion 


    public function __construct($dsn = 'mysql:host=localhost;dbname=xxx_2013',$username = 'root',$password = 'xxx') 
    { 
    $this->dsn = $dsn; 
     $this->username = $username; 
     $this->password = $password; 
     $this->connection(); 
    } 


    private function connection() 
    { 
     try 
     { 
      $this->connection = new PDO($this->dsn, $this->username, $this->password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")); 
      $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
     } 
     catch (PDOException $e) 
     { 
      # call the get_error function 
      $this->get_error($e); 
     } 
     // return $this->connection; 
    } 
... 
} 

편집 :

class database extends common 
{ 
    /** 
    * Set the class property. 
    */ 
    protected $connection = null; 
    protected $dsn,$username,$password; 

    /** 
    * Set the class contructor. 
    * @reference: http://us.php.net/manual/en/language.oop5.magic.php#object.sleep 
    */ 
    public function __construct($dsn,$username,$password) 
    { 
     $this->dsn = $dsn; 
     $this->username = $username; 
     $this->password = $password; 
     //$this->connect(); 


    } 

    /** 
    * make the pdo connection. 
    * @return object $connection 
    */ 
    public function connect() 
    { 
     try 
     { 
      # MySQL with PDO_MYSQL 
      # To deal with special characters and Chinese character, add charset=UTF-8 in $dsn and array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"). 

      $this->connection = new PDO($this->dsn, $this->username, $this->password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")); 
      $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
     } 
     catch (PDOException $e) 
     { 
      # call the get_error function 
      $this->get_error($e); 
     } 
    } 

    /** 
    * get the number of rows in a result as a value string. 
    * @param string $query 
    * @param array $params 
    * @return number 
    */ 
    public function num_rows($query, $params = array()) 
    { 
     try 
     { 
      # create a prepared statement 
      $stmt = $this->connection->prepare($query); 

      # if $params is not an array, let's make it array with one value of former $params 
      if (!is_array($params)) $params = array($params); 

      # execute the query 
      $stmt->execute($params); 

      # return the result 
      return $stmt->rowCount(); 
     } 
     catch (PDOException $e) 
     { 
      # call the get_error function 
      $this->get_error($e); 
     } 
    } 

    /** 
    * fetch a single row of result as an array (= one dimensional array). 
    * @param string $query 
    * @param array $params 
    * @param boolean $array_to_object 
    * @return object/ array 
    */ 
    public function fetch_assoc($query, $params = array(), $array_to_object = true) 
    { 
     try 
     { 
      # prepare the query 
      $stmt = $this->connection->prepare($query); 

      # if $params is not an array, let's make it array with one value of former $params 
      if (!is_array($params)) $params = array($params); 

      # the line 
      //$params = is_array($params) ? $params : array($params); 
      # is simply checking if the $params variable is an array, and if so, it creates an array with the original $params value as its only element, and assigns the array to $params. 

      # This would allow you to provide a single variable to the query method, or an array of variables if the query has multiple placeholders. 

      # The reason it doesn't use bindParam is because the values are being passed to the execute() method. With PDO you have multiple methods available for binding data to placeholders: 

      # bindParam 
      # bindValue 
      # execute($values) 

      # The big advantage for the bindParam method is if you are looping over an array of data, you can call bindParam once, to bind the placeholder to a specific variable name (even if that variable isn't defined yet) and it will get the current value of the specified variable each time the statement is executed. 

      # execute the query 
      $stmt->execute($params); 

      # return the result 
      if($array_to_object) return parent::array_to_object($stmt->fetch()); 
       else return $stmt->fetch(); 
     } 
     catch (PDOException $e) 
     { 
      # call the get_error function. 
      $this->get_error($e); 
     } 

     /* 
     or, 

     catch (Exception $e) 
     { 
      // Echo the error or Re-throw it to catch it higher up where you have more 
      // information on where it occurred in your program. 
      // e.g echo 'Error: ' . $e->getMessage(); 

      throw new Exception(
       __METHOD__ . 'Exception Raised for sql: ' . var_export($sql, true) . 
       ' Params: ' . var_export($params, true) . 
       ' Error_Info: ' . var_export($this->errorInfo(), true), 
       0, 
       $e); 
     } 
     */ 
    } 

    /** 
    * fetch a multiple rows of result as a nested array (= multi-dimensional array). 
    * @param string $query 
    * @param array $params 
    * @param boolean $array_to_object 
    * @return object/ array 
    */ 
    public function fetch_all($query, $params = array(), $array_to_object = true) 
    { 
     try 
     { 
      # prepare the query 
      $stmt = $this->connection->prepare($query); 

      # if $params is not an array, let's make it array with one value of former $params 
      if (!is_array($params)) $params = array($params); 

      # when passing an array of params to execute for a PDO statement, all values are treated as PDO::PARAM_STR. 
      # use bindParam to tell PDO that you're using INTs 
      # wrap the bindParam function in a foreach that scan your parameters array 
      # it's $key + 1 because arrays in PHP are zero-indexed, but bindParam wants the 1st parameter to be 1, not 0 (and so on). 
      /* 
      foreach($params as $key => $param) 
      { 
       if(is_int($param)) 
       { 
        $stmt->bindParam($key + 1, $param, PDO::PARAM_INT); 
       } 
       else 
       { 
        $stmt->bindParam($key + 1, $param, PDO::PARAM_STR); 
       } 
      } 

      # execute the query 
      $stmt->execute(); 
      */ 

      # execute the query 
      $stmt->execute($params); 

      # return the result 
      if($array_to_object) return parent::array_to_object($stmt->fetchAll(PDO::FETCH_ASSOC)); 
       else return $stmt->fetchAll(PDO::FETCH_ASSOC); 
     } 
     catch (PDOException $e) 
     { 
      # call the get_error function 
      $this->get_error($e); 
     } 
    } 

    /** 
    * return the current row of a result set as an object. 
    * @param string $query 
    * @param array $params 
    * @return object 
    */ 
    public function fetch_object($query, $params = array()) 
    { 
     try 
     { 
      # prepare the query 
      $stmt = $this->connection->prepare($query); 

      # if $params is not an array, let's make it array with one value of former $params 
      if (!is_array($params)) $params = array($params); 

      # execute the query 
      $stmt->execute($params); 

      # return the result 
      return $stmt->fetchObject(); 
      //return $stmt->fetch(PDO::FETCH_OBJ); 
     } 
     catch (PDOException $e) 
     { 
      # call the get_error function 
      $this->get_error($e); 
     } 
    } 

    /** 
    * insert or update data. 
    * @param string $query 
    * @param array $params 
    * @return boolean - true. 
    */ 
    public function run_query($query, $params = array()) 
    { 
     try 
     { 
      $stmt = $this->connection->prepare($query); 
      $params = is_array($params) ? $params : array($params); 
      $stmt->execute($params); 
      return true; 
     } 
     catch (PDOException $e) 
     { 
      # call the get_error function 
      $this->get_error($e); 
     } 
    } 

    /** 
    * with __sleep, you return an array of properties you want to serialize. the point is to be able to exclude properties that are not serializable. eg: your connection property. 
    * @return array 
    */ 
    public function __sleep() 
    { 
     return array('dsn', 'username', 'password'); 
    } 

    /** 
    * the intended use of __wakeup() is to reestablish any database connections that may have been lost during serialization and perform other reinitialization tasks. 
    */ 
    public function __wakeup() 
    { 
     $this->connect(); 
     //$this->connection = new PDO($this->dsn, $this->username, $this->password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")); 
     //$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    } 

    /** 
    * display error. 
    * @return string 
    */ 
    public function get_error($e) 
    { 
     $this->connection = null; 
     die($e->getMessage()); 
    } 

    /** 
    * close the database connection when object is destroyed. 
    */ 
    public function __destruct() 
    { 
     # set the handler to NULL closes the connection propperly 
     $this->connection = null; 
    } 
} 

사용법 :

$database = new database(DSN,DB_USER,DB_PASS); 
$connection = $database->connect(); 
var_dump($connection); 

결과,

null

그것이 있어야

,

object(database)[1] 
    protected 'connection' => 
    object(PDO)[2] 
    protected 'dsn' => string 'mysql:host=localhost;dbname=xxx_2013' (length=42) 
    protected 'username' => string 'xxx' (length=4) 
    protected 'password' => string 'xxx' (length=5) 
+0

공개. 그렇지 않으면 객체를 생성 할 수 없습니다. – AmazingDreams

+0

비공개로 설정하면 응용 프로그램의 주어진 세션에 db 연결 인스턴스가 하나만 존재할 수 있습니다. – DevZer0

+0

^그게 싱글 톤이라고합니다. ** BAD ** : D – Jimbo

답변

7

번호 당신이 잘못 생각하고 있습니다. 공개 메소드은 클래스를 사용하는 다른 개발자에게 제공하는 API입니다.

수업을 마치고 나면 다른 개발자에게 문서를 넘겨주고 있다고 상상해보십시오. 다른 개발자가 사용할 수있는 "끝점"을 나열합니다. 이들은 현재 : 그것은 무엇을 확인하기 위해 코드를보고 다른 개발자가 더 의미로

  • __construct()
  • connection()

은 분명히 당신이 connect()의 라인을 따라 뭔가 더 할 connection() 원하는 그것을 않습니다. 심지어 makeConnection()이 좋습니다. 싱글 :

싱글 톤은 개인에 대한 생성자는 다음과 같은 이유로 일반적으로 설정

BAD 있습니다. 글로벌 상태, 싱글 톤 (singleton) 등을 피하기를 원합니다. 그들은 나쁜 습관이고, 열심히 테스트하고 더 많이 테스트합니다.

개체가 공유 메모리에있는 언어에서는 싱글 톤을 사용하여 메모리 사용을 낮게 유지할 수 있습니다. 두 객체를 만드는 대신 전역 공유 응용 프로그램 메모리에서 기존 인스턴스를 참조합니다. PHP에서는 이러한 응용 프로그램 메모리가 없습니다. 하나의 요청에서 생성 된 싱글 톤은 정확히 그 요청에 따라 살아납니다. 같은 시간에 완료된 다른 요청에서 생성 된 싱글 톤은 여전히 ​​완전히 다른 인스턴스입니다. 따라서 싱글 톤의 두 가지 주요 목적 중 하나는 여기에 적용되지 않습니다.

읽기 싱글 그냥 미친 이유의 심층적 인 이해의 이상 this post. 둘 이상의 연결 인스턴스가 필요없는 경우 을 하나 생성하지 마십시오. 도움을 줄 수는 없지만 아키텍처를 만들 수 없다면 아키텍처를 다시 생각해 봐야합니다. DB를 처리하는 것은 일반적으로 수행중인 작업의 초기 단계이기 때문에 너무 나쁘지 않아야합니다.

닫는 중 생성자는 public이어야합니다. 왜? 그래서 그것을 사용하는 개발자 (다른 개발자로서의 자신을 상상해보십시오)는 의도 된 용도로 사용할 수 있습니다.


추가 노트 :

  1. 사용자 이름/암호가 하드 클래스 생성자로 코딩되어서는 안된다, 당신은 객체를 생성 할 때 이러한을 통과해야한다.

  2. $this->connection()을 생성자에서 호출하십시오. 네가 그렇게한다면 너는 거기에 모든 것을 밀어 넣을 수도있다.

    $db = new pdo_connection($username, $password, $etc);
    $db->connection();

이 당신이 원하는 위치의 주위에 당신의 개체를 전달할 수 있다는 것을 의미하지만, 당신이 connection() 방법을 실행할 때 자원 만 (연결 생성) 사용 대신 호출합니다.

+0

확인. 답변 해주셔서 감사합니다. 내가 이해하기 힘들 기 때문에 나는 싱글 톤을 가지 않을 것이다. – laukok

+0

두 번째 메모를 이해할 수 없습니다. 어떻게 할거예요? 감사! – laukok

+1

그래서 새로운 pdo_connection을 생성하면, 곧바로'connection()'을 실행하면됩니다.생성자에서'$ this-> connection();'을 제거하십시오. – Jimbo