PHP PDO: dovremmo impostare `function __construct 'di pdo in` private` o `public`?

Dovremmo impostare la function __construct di pdo __build su private o public ? Sarà un argomento di vulnerabilità se lo public ?

Ecco la mia class di 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, arrays(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; } ... } 

MODIFICARE:

 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 arrays(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"). $this->connection = new PDO($this->dsn, $this->username, $this->password, arrays(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 arrays $params * @return number */ public function num_rows($query, $params = arrays()) { try { # create a prepared statement $stmt = $this->connection->prepare($query); # if $params is not an arrays, let's make it arrays with one value of formsr $params if (!is_arrays($params)) $params = arrays($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 arrays ( = one dimensional arrays). * @param string $query * @param arrays $params * @param boolean $arrays_to_object * @return object/ arrays */ public function fetch_assoc($query, $params = arrays(), $arrays_to_object = true) { try { # prepare the query $stmt = $this->connection->prepare($query); # if $params is not an arrays, let's make it arrays with one value of formsr $params if (!is_arrays($params)) $params = arrays($params); # the line //$params = is_arrays($params) ? $params : arrays($params); # is simply checking if the $params variable is an arrays, and if so, it creates an arrays with the original $params value as its only element, and assigns the arrays to $params. # This would allow you to provide a single variable to the query method, or an arrays 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 arrays 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($arrays_to_object) return parent::arrays_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. // eg 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 arrays ( = multi-dimensional arrays). * @param string $query * @param arrays $params * @param boolean $arrays_to_object * @return object/ arrays */ public function fetch_all($query, $params = arrays(), $arrays_to_object = true) { try { # prepare the query $stmt = $this->connection->prepare($query); # if $params is not an arrays, let's make it arrays with one value of formsr $params if (!is_arrays($params)) $params = arrays($params); # when passing an arrays 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 arrays # it's $key + 1 because arrayss 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($arrays_to_object) return parent::arrays_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 arrays $params * @return object */ public function fetch_object($query, $params = arrays()) { try { # prepare the query $stmt = $this->connection->prepare($query); # if $params is not an arrays, let's make it arrays with one value of formsr $params if (!is_arrays($params)) $params = arrays($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 arrays $params * @return boolean - true. */ public function run_query($query, $params = arrays()) { try { $stmt = $this->connection->prepare($query); $params = is_arrays($params) ? $params : arrays($params); $stmt->execute($params); return true; } catch (PDOException $e) { # call the get_error function $this->get_error($e); } } /** * with __sleep, you return an arrays of properties you want to serialize. the point is to be able to exclude properties that are not serializable. eg: your connection property. * @return arrays */ public function __sleep() { return arrays('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, arrays(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; } } 

Uso:

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

risultato,

null

dovrebbe essere,

 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) 

No. Stai pensando a questo torto. I tuoi methods pubblici sono l'API che stai dando ad altri sviluppatori che usano la tua class.

Alla fine della stesura della tua class, immagina di passare la tua documentazione a un altro sviluppatore. Elencherai "endpoint" che altri sviluppatori possono utilizzare. Questi attualmente sono:

  • __construct()
  • connection()

Chiaramente vuoi che connection() sia qualcosa di più sulla linea di connect() perché ha più senso che un altro sviluppatore guardi il tuo codice per vedere cosa fa. Anche makeConnection() è migliore.

I singleton sono BAD

L'impostazione di un constructor su privato è solitamente per il seguente motivo: un singleton. Volete evitare lo stato globale, i singleton ecc. – sono cattive pratiche, rendono difficile il test e altro ancora.

Nelle lingue in cui gli oggetti vivono nella memory condivisa, è ansible utilizzare Singletons per mantenere basso l'utilizzo della memory. Invece di creare due oggetti, fai riferimento a un'istanza esistente dalla memory dell'applicazione condivisa a livello globale. In PHP non esiste una memory applicativa di questo tipo. Un Singleton creato in una Richiesta vive esattamente per quella richiesta. Un Singleton creato in un'altra richiesta eseguita allo stesso tempo è ancora un'istanza completamente diversa. Pertanto, uno dei due scopi principali di Singleton non è applicabile qui.

Leggi questo post per saperne di più sul perché i singleton sono semplicemente stupidi. Se non si desidera più di un'istanza di una connessione, non crearne una . Se non puoi fare a less di crearne uno, devi rivedere la tua architettura (il che non dovrebbe essere un problema perché la gestione delle cose di DB è di solito nelle prime fasi di qualunque cosa tu stia facendo).

In chiusura, il tuo constructor deve essere pubblico . Perché? Quindi gli sviluppatori (immaginatevi come un altro sviluppatore) che lo usano possono usarlo per il suo scopo.


Note extra:

  1. Il tuo nome utente / password non dovrebbero essere codificati nel constructor della class, devi passarli quando crei l'object.

  2. Non call $this->connection() dal tuo constructor. Potresti anche spingerlo tutto dentro se lo fai. Invece, chiama:

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

Ciò significa che è ansible passare il proprio object ovunque si desideri, ma si utilizzano solo risorse (creare la connessione) quando si esegue il metodo connection() .