Использование PDO в классах
У меня есть несколько классов, которые выполняют некоторые MySQL-запросы и подготовленные операторы. Тем не менее, я теряюсь в том, как включить мой объект PDO в эти классы. Например, я хочу сделать что-то вроде этого:
<?php
$dbh = new PDO(...);
class Foo extends PDO {
public $dbh;
public function bar() {
$this->dbh->prepare('SELECT * FROM table');
$this->dbh->execute();
}
}
?>
К сожалению, он не работает. Может ли кто-нибудь предложить элегантный способ сделать это? Спасибо за ваше время. Извините, что я новичок в этом вопросе, пожалуйста, оставьте любые комментарии, если вы неясны ни о чем, и я сделаю все возможное, чтобы ответить!
Ответы
Ответ 1
Вы можете создать соединение с базой данных в классе, реализующем одноэлементный шаблон.
Соединение будет выполнено один раз, и этот класс будет легко доступен для всех ваших других объектов/скриптов.
Я использую класс, называемый "Core" в следующем примере:
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
}
этот класс принимает параметры из статического класса под названием "Config", где вы можете сохранить конфигурацию:
<?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');
во всех ваших сценариях/объектах вам просто нужно получить экземпляр Core, а затем запросить 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....
Если вам нужна дополнительная информация об одноэлементном взгляде на PHP doc http://php.net/manual/en/language.oop5.patterns.php
Ответ 2
Ниже приведен пример более полного рабочего примера вырезания и вставки Guillaume Boschini.
Таблица заполненных БД (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;
В/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
}
?>
В/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>';
}
?>
Сообщение выше действительно помогло мне. Этот пост, который я сейчас делаю, заставил бы меня туда, где я хотел быть быстрее. Вот и все. Если что-то не так, я буду рядом, чтобы исправить это.
Ответ 3
$dbh
не входит в область Foo
, сделайте это вместо этого:
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();
}
}
Кроме того, Foo
не нужно расширять PDO
.
Ответ 4
я нашел лучшее решение:
когда у вас есть соединение PDO вне вашего класса и не можете использовать это соединение внутри класса, отправьте этот объект PDO в конструктор в качестве параметра
///это мое соединение pdo
$pdo_object = new PDO('mysql:host=localhost;dbname=blabla','user','pw');
///im создавая экземпляр этого класса как obj
$dataObj=new class_name($pdo_obj);
/////внутри класса: упрощенного
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