2010-01-12 5 views
26

Ho alcune classi che eseguono alcune query MySQL e istruzioni preparate. Tuttavia, mi sono perso in come incorporare il mio oggetto PDO all'interno di quelle classi. Per esempio, io voglio fare qualcosa di simile:Uso di PDO nelle classi

<?php 

$dbh = new PDO(...); 

class Foo extends PDO { 
    public $dbh; 

    public function bar() { 
     $this->dbh->prepare('SELECT * FROM table'); 
     $this->dbh->execute(); 

    } 
} 


?> 

Purtroppo, non funziona. Qualcuno può suggerire un modo elegante per farlo? Grazie per il tuo tempo. Scusa se sono nuovo a questo, per favore lasciate qualsiasi commento se non siete sicuri di nulla e farò del mio meglio per rispondere!

+7

Fa la tua classe Foo veramente _extend_ class DOP? Oppure un'istanza di FOO semplicemente _use_ e instance PDO. Il tuo esempio sembra più che usare che estendere. – VolkerK

risposta

59

È possibile creare un'istanza della connessione al database in una classe che implementa il modello singleton. La connessione verrà eseguita una volta e questa classe sarà facilmente accessibile da tutti gli altri oggetti/script.

io uso una classe chiamata "Core" nel seguente esempio;

class Core 
{ 
    public $dbh; // handle of the db connexion 
    private static $instance; 

    private function __construct() 
    { 
     // building data source name from config 
     $dsn = 'pgsql:host=' . Config::read('db.host') . 
       ';dbname=' . Config::read('db.basename') . 
       ';port='  . Config::read('db.port') . 
       ';connect_timeout=15'; 
     // getting DB user from config     
     $user = Config::read('db.user'); 
     // getting DB password from config     
     $password = Config::read('db.password'); 

     $this->dbh = new PDO($dsn, $user, $password); 
    } 

    public static function getInstance() 
    { 
     if (!isset(self::$instance)) 
     { 
      $object = __CLASS__; 
      self::$instance = new $object; 
     } 
     return self::$instance; 
    } 

    // others global functions 
} 

parametri questa classe prendere da una classe statica denominata "Config" dove è possibile memorizzare la configurazione:

<?php 
class Config 
{ 
    static $confArray; 

    public static function read($name) 
    { 
     return self::$confArray[$name]; 
    } 

    public static function write($name, $value) 
    { 
     self::$confArray[$name] = $value; 
    } 

} 

// db 
Config::write('db.host', '127.0.0.1'); 
Config::write('db.port', '5432'); 
Config::write('db.basename', 'mydb'); 
Config::write('db.user', 'myuser'); 
Config::write('db.password', 'mypassword'); 

in tutti gli script/oggetti che si hanno solo per ottenere l'istanza di Core e poi interrogare il DB

$sql = "select login, email from users where id = :id"; 

try { 
    $core = Core::getInstance(); 
    $stmt = $core->dbh->prepare($sql); 
    $stmt->bindParam(':id', $this->id, PDO::PARAM_INT); 

    if ($stmt->execute()) { 
     $o = $stmt->fetch(PDO::FETCH_OBJ); 
     // blablabla.... 

Se avete bisogno di ulteriori informazioni su aspetto Singleton al PHP doc http://php.net/manual/en/language.oop5.patterns.php

+2

Wow, è fantastico e funziona perfettamente. Grazie per il suggerimento, è bello ed elegante :) Questa sarà sicuramente una delle pratiche di codifica che rimarrà con me attraverso diversi progetti! – axsuul

+0

prego; Io uso la classe Core per memorizzare altre cose utili che devono essere accessibili in molti dei miei script, come l'oggetto che contiene l'utente registrato ... è molto conveniente –

+4

Penso che 'istanza privata $ statico;' deve essere dichiarato come proprietà, altrimenti si otterrà l'accesso alla proprietà statica non dichiarata: Core :: $ istanza. – Ben

3

$dbh non rientra nel campo di applicazione Foo, fare questo, invece:

class Foo /*extends PDO*/ 
{ 
    public $dbh; 

    public function __construct() 
    { 
     $dbh = new PDO(/*...*/); 
    } 

    public function bar() 
    { 
     $this->dbh->prepare('SELECT * FROM table'); 
     return $this->dbh->execute(); 
    } 
} 

Inoltre, Foo non ha bisogno di estendere PDO.

+0

Questo rallenterebbe il database/lo script perché sto creando una nuova connessione ogni volta che creo un oggetto? – axsuul

+0

Perché dovresti istanziare l'oggetto più di una volta? –

+0

Intendevo dire che ho 14 * diversi * oggetti in uno script, e tutti hanno bisogno di connessioni al database, quindi non dovrei fare 14 connessioni al database? – axsuul

6

Ecco un taglio di lavoro per lo più completo & incolla l'esempio della risposta di Guillaume Boschini sopra.

Una tabella DB popolata (MySQL):

CREATE TABLE `useraddress` (                                  
    `addressid` int(10) unsigned NOT NULL AUTO_INCREMENT,                                
    `userid` int(10) unsigned NOT NULL,                                    
    `addresstitle` char(100) NOT NULL,                               
    `streetaddressa` char(100) NOT NULL, 
    `streetaddressb` char(100) DEFAULT NULL, 
    `unit` char(50) DEFAULT NULL, 
    `city` char(50) NOT NULL, 
    `state` char(2) NOT NULL, 
    `zip` int(5) NOT NULL, 
    `zipplusfour` int(4) DEFAULT NULL, 
    PRIMARY KEY (`addressid`), 
    KEY `userid` (`userid`), 
    CONSTRAINT `useraddress_fk_1` FOREIGN KEY (`userid`) REFERENCES `user` (`userid`) 
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

In /DBLibrary/pdocore.php:

<?php 

    Config::write('db.host', 'localhost'); 
    Config::write('db.port', '3306'); 
    Config::write('db.basename', 'DBName'); 
    Config::write('db.user', 'DBUser'); 
    Config::write('db.password', 'DBPassword'); 

    class Config { 

     static $confArray; 

     public static function read($name) { 
      return self::$confArray[$name]; 
     } 

     public static function write($name, $value) { 
      self::$confArray[$name] = $value; 
     } 

    } 

    class Core { 
     public $dbh; // handle of the db connection 
     private static $instance; 

     private function __construct() { 

      // building data source name from config 
      $dsn = 'mysql:host=' . Config::read('db.host') . ';dbname=' . Config::read('db.basename') . ';port=' . Config::read('db.port') .';connect_timeout=15'; 

      // getting DB user from config 
      $user = Config::read('db.user'); 

      // getting DB password from config 
      $password = Config::read('db.password'); 

      $this->dbh = new PDO($dsn, $user, $password); 
      $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

     } 

     public static function getInstance() { 
      if (!isset(self::$instance)) { 
       $object = __CLASS__; 
       self::$instance = new $object; 
      } 
      return self::$instance; 
     } 

     // others global functions 
    } 
?> 

In /objectsLibrary/SYS_UserAddress.php:

<?php 

    define('k_uaddress_addressid','addressid'); 
    define('k_uaddress_userid','userid'); 
    define('k_uaddress_addresstitle','addresstitle'); 
    define('k_uaddress_addressa','streetaddressa'); 
    define('k_uaddress_addressb','streetaddressb'); 
    define('k_uaddress_unit','unit'); 
    define('k_uaddress_city','city'); 
    define('k_uaddress_state','state'); 
    define('k_uaddress_zip','zip'); 
    define('k_uaddress_zipplusfour','zipplusfour'); 

    require_once '../DBLibrary/pdocore.php'; 

    class SYS_UserAddress { 

     public $addressid; 
     public $userid; 
     public $addresstitle; 
     public $addressa; 
     public $addressb; 
     public $unit; 
     public $city; 
     public $state; 
     public $zip; 
     public $zipplusfour; 

     public function SYS_UserAddressByAddressId($_addressid) { 

      $returnValue=FALSE; 

      $query='select * from useraddress where ' . k_uaddress_addressid . '=:addressid'; 

      try { 
       $pdoCore = Core::getInstance(); 
       $pdoObject = $pdoCore->dbh->prepare($query); 

       $queryArray = array(':addressid'=>$_addressid); 

       if ($pdoObject->execute($queryArray)) { 

        $pdoObject->setFetchMode(PDO::FETCH_ASSOC);; 

        while ($addressrow = $pdoObject->fetch()) { 

         $this->addressid=$addressrow[k_uaddress_addressid]; 
         $this->userid=$addressrow[k_uaddress_userid]; 
         $this->addresstitle=$addressrow[k_uaddress_addresstitle]; 
         $this->addressa=$addressrow[k_uaddress_addressa]; 
         $this->addressb=$addressrow[k_uaddress_addressb]; 
         $this->unit=$addressrow[k_uaddress_unit]; 
         $this->city=$addressrow[k_uaddress_city]; 
         $this->zip=$addressrow[k_uaddress_zip]; 
         $this->zipplusfour=$addressrow[k_uaddress_zipplusfour]; 

        } 
        $returnValue=TRUE; 
       } 
      } 
      catch(PDOException $pe) { 
       trigger_error('Could not connect to MySQL database. ' . $pe->getMessage() , E_USER_ERROR); 
      } 

      return $returnValue; 

     } 
    } 

    $test=1; 
    $testAddressId=2; 

    if($test>0) { 

     $testAddress = new SYS_UserAddress(); 

     $testAddress->SYS_UserAddressByAddressId($testAddressId); 

     echo '<pre>'; 
     echo print_r($testAddress); 
     echo '</pre>'; 

    } 

?> 

Il post sopra mi ha davvero aiutato. Questo post che sto facendo ora mi avrebbe portato dove volevo essere più veloce. Questo è tutto. Se qualcosa non va, sarò in giro per sistemarlo.

+0

ad esempio voglio usare PHPmailler con questo. dove dovrei aggiungerlo o come? grazie –

+0

Questo è stato un buon inizio, tutte le mie inclusioni e richieste non sono più nel mio webroot. Selezioneremo un nome di file arbitrario-- 'webpage.php'. Nel tuo file "webpage.php" dovresti richiedere /objectsLibrary/SYS_UserAddress.php e /thirdPartyLibrary/phpMailer.php; allora saresti libero di usare entrambi in "webpage.php". – BradChesney79

0

ho trovato una soluzione migliore: quando si dispone di una connessione DOP al di fuori della classe e non posso usare quella connessione all'interno della classe, inviare tale oggetto PDO al costruttore come parametro

/// thats il mio DOP collegamento

$pdo_object = new PDO('mysql:host=localhost;dbname=blabla','user','pw'); 

/// im creando l'istanza di tale classe come obj

$dataObj=new class_name($pdo_obj); 

///// all'interno della classe ::: s imprevisto

class class_name{ 

private $handler;//// this is what i use for PDO connection inside the class 

public function __construct($connection_name){ 

    if(!empty($connection_name)){ 
     $this->handler=$connection_name; 
    ///its a great thing that holy php doesnt care much about variant types. any variant is able to carry any object (like PDO obj) 
    }else{ 
     throw new Exception("cant connect bla bla..."); 
    } 



}/////contruct fx 

////how i use that pdo connection which is implamented to a local var called handler with any sql query is : 

$dataSet= $this->handler->query("SELECT * FROM users WHERE ...."); 



}////endof class 
+0

C'è qualche ragione ** non ** per fare questo? –