2012-03-15 5 views
2

Я пытаюсь понять, как использовать PDO с классом «соединение».PDO класс подключения/код и класс дизайна

class db { 

    private static $dbh; 

    private function __construct(){} 
    private function __clone(){} 

    public static function connect() { 
     if(!self::$dbh){ 
      self::$dbh = new PDO("mysql:host=localhost;dbname=database", "user", "password"); 
      self::$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
     } 
     return self::$dbh; 
    } 

    final public static function __callStatic($chrMethod, $arrArguments) { 
     $dbh = self::connect(); 
     return call_user_func_array(array($dbh, $chrMethod), $arrArguments); 
    } 
} 

Я взял выше от http://php.net/manual/en/book.pdo.php, и слегка изменили переменные, но мне интересно, как я потом подключить к объекту соединения PDO в этом дб классе?

$dbh = new db; //intiate connection??? 

$stmt = $dbh->prepare("SELECT * FROM questions WHERE id = :id"); // or should I do db::prepare.. ??? 
$stmt->bindParam(':id', $_GET['testid'], PDO::PARAM_INT); 

if ($stmt->execute()) { 
    while ($row = $stmt->fetch()){ 
     print_r($row); 
    } 
} 

Любые идеи, пожалуйста? спасибо

+0

Я не пытаюсь понять, почему вы используете глобальные методы статического класса. – hakre

ответ

5

Это более или менее, как я это делаю. Я не уверен, что это лучший способ сделать это, но это работает для меня.

Мой заводский класс является CORE моего кода. Отсюда я создаю все классы, с которыми я работаю. Мой заводский класс сохраняется в отдельном файле factory.class.php.

Имея класс фабрики, мне нужно включать только файлы классов только один раз. Если бы у меня не было этого, я бы включил файлы классов для каждого файла, который должен был его использовать. Если мне нужно обновить имя файла класса позже, мне нужно только сделать обновление в файле фабричного класса.

Другой причиной создания фабричного объекта было сокращение количества соединений с БД.

откладываю каждый класс в отдельный файл

Фабрика класса

include_once('person.class.php'); 
include_once('tracking.class.php'); 
include_once('costAnalyzis.class.php'); 
include_once('activity.class.php'); 

class Factory { 
    function new_person_obj($id = NULL) { return new Person(Conn::get_conn(), $id); } 
    function new_tracking_obj($id = NULL) { return new Tracking(Conn::get_conn(), $id); } 
    function new_costAnalyzis_obj() { return new CostAnalyzis(Conn::get_conn()); } 
    function new_activity_obj() { return new Activity(Conn::get_conn()); } 
}  

класс Connection

// I have this class in the same file as Factory class 
// This creates DB connection and returns any error messages 
class Conn { 
    private static $conn = NULL; 

    private function __construct() {} 

    private static function init() { 
     $conf = self::config(); 
     try { 
     self::$conn = new PDO($conf['dsn'], $conf['user'], $conf['pass'], array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")); 
     } 
     catch (PDOException $e) { 
     // We remove the username if we get [1045] Access denied 
     if (preg_match("/\b1045\b/i", $e->getMessage())) 
      echo "SQLSTATE[28000] [1045] Access denied for user 'name removed' @ 'localhost' (using password: YES)"; 
     else 
      echo $e->getMessage(); 
     } 
    } 

    public static function get_conn() { 
    if (!self::$conn) { self::init(); } 
    return self::$conn; 
    } 

    // I used to get login info from config file. Now I use Wordpress constants 
    private static function config() { 
    $conf = array(); 

    $conf['user'] = DB_USER; //$config['db_user']; 
    $conf['pass'] = DB_PASSWORD; //$config['db_password']; 
    $conf['dsn']  = 'mysql:dbname='.DB_NAME.';host='.DB_HOST; 

    return $conf; 
    } 
} 

Различные объекты класса

Это ваши классы. Здесь вы работаете с вашими данными. В моем собственном коде я использую трехуровневую архитектуру, разделяющую презентацию, с уровня бизнес-уровня и объекта данных.

class Person extends PersonDAO { 

    function getPersonData($id) { 
    $result = parent::getPersonData($id); 

    // Here you can work with your data. If you do not need to handle data, just return result 
    return $result; 
    } 
} 


// I only have SQL queries in this class and I only return RAW results. 
class PersonDAO { 

    // This variable is also available from you mother class Person 
    private $db; 

    // Constructor. It is automatically fired when calling the function. 
    // It must have the same name as the class - unless you define 
    // the constructor in your mother class. 
    // The &$db variable is the connection passed from the Factory class. 
    function PersonDAO (&$db) { 
     $this->db = &$db; 
    } 


    public function get_data($id) { 
    $sql ="SELECT a, b, c 
      FROM my_table 
      WHERE id = :id"; 

    $stmt = $this->db->prepare($sql); 
    $stmt->execute(array(':id'=> $id)); 
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC); 

    return $result; 
    } 

    public function get_some_other_data() { 
    $sql ="SELECT a, b, c 
      FROM my_table_b"; 

    $result = $stmt->fetchAll(PDO::FETCH_ASSOC); 

    return $result;  
    } 
} 

Сделайте то же самое для своих других классов.

Собираем все вместе

Обратите внимание, что мы только включить один файл, заводские файлы. Все другие файлы классов включены в файл класса Factory.

// Include factory file 
include_once('factory.class.php'); 

//Create your factory object 
$person = Factory::new_person_obj(); 

//Get person data 
$data = $person->getPersonData('12'); 

// output data 
print_r($data); 
+0

Большое спасибо за ваш ответ Стивен. Я получаю «Вызовите функцию-член new_obj() для не-объекта в ...» Я обновил sql-запрос и информацию о базе данных ... могли бы вы кратко комментировать, что делает каждая часть? Извините, я новичок в ООП ..! – Tim

+0

Я тоже не использую WP .. но все равно определил эти переменные. Также как добавить новые запросы? Спасибо большое :) – Tim

+0

Я пробовал это тоже с той же ошибкой ... :( – Tim

3

Как я понял, вы хотите иметь «класс подключения», который реализует отложенной загрузки для экземпляра PDO. И тогда вы хотите, чтобы объекты в вашем коде имели доступ к этому соединению из любого места в коде, эффективно создавая синглтон.

Не делайте этого.

Вы очищаете глобальное состояние в своем приложении, и все ваши классы с поддержкой DB тесно связаны с NAME класса соединения.

Я бы порекомендовал немного другой подход.Как уже указывалось @Steven, вы должны использовать фабрику для создания объектов, для которых требуется соединение с БД.

Вот упрощенная реализация.

class DataMapperFactory 
{ 
    protected $provider = null; 
    protected $connection = null; 

    public function __construct(Closure $provider) 
    { 
     $this->provider = $provider; 
    } 

    public function create($name) 
    { 
     if ($this->connection === null) 
     { 
      $this->connection = call_user_func($this->provider); 
     } 
     return new $name($this->connection); 
    } 

} 

Вы бы использовать его вроде как это:

$provider = function() 
{ 
    $instance = new PDO('mysql:......'); 
    $instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    $instance->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 
    return $instance; 
}; 

$factory = new DataMapperFactory($provider); 

Теперь каждый раз, когда вы выполняете $factory->create('SomeClass'), это создаст новый экземпляр этого класса и обеспечить его надлежащее соединение DB в конструкторе. И, когда он будет выполнен в первый раз, он откроет соединение с БД.

Смежные вопросы