do you guys have an idea why I can't close the mysql connection?
Here is my code:
class DatabaseFactory {
private static $factory;
private $connection = array(
"DB_HOST" => "localhost",
"DB_PASS" => "*************",
"DB_USER" => "*************",
"DB_PORT" => "3306",
"DB_CHARSET" => "utf8"
);
public static
function getFactory() {
if(!self::$factory) {
self::$factory = new DatabaseFactory();
}
return self::$factory;
}
private $db;
public
function getconnection($name) {
echo "opened";
try {
$options = array(
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_OBJ,
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_WARNING
);
$this->db = new \PDO('mysql:host='.$this->connection["DB_HOST"].';dbname='.$name.';port=' .$this->connection["DB_PORT"].';charset='.$this->connection["DB_CHARSET"], $this->connection["DB_USER"], $this->connection["DB_PASS"], $options);
} catch (PDOException $e) {
exit($e->getMessage());
}
return $this->db;
}
public
function __destruct() {
echo "closed";
try {
$this->db = null;
unset($this->db);
} catch (PDOException $e) {
exit($e->getMessage());
}
}
}
$database = DatabaseFactory::getFactory()->getconnection("Admin");
$query = $database->prepare("SELECT * FROM tester WHERE t_u_id = :u_id");
$query->execute(array(":u_id" => "281123341528-D050C4-91A0BA-1CB0C8-8112334152855AC373"));
The connection is connecting but it is not closed.
The method __destruct will be called but the mysql total connections count doesn't decrease.
Why don't you implement and call a method (manually instead of relying on __destruct()) like Fil does in his response here?
Add the following static method to your DatabaseFactory class
static function closeConnection(&$conn) {
$conn=null;
}
So after your connections, you can NULL your connection reference (which is akin to calling $mysqli_conn->close();) later in your code like this:
$database = DatabaseFactory::getFactory()->getconnection("Admin");
$query = $database->prepare("SELECT * FROM tester WHERE t_u_id = :u_id");
$query->execute(array(":u_id" => "281123341528-D050C4-91A0BA-1CB0C8-8112334152855AC373"));
DatabaseFactory::closeConnection($database)
EDIT:
Also, I wanted to mention that by relying on __destruct(), you are subject to the following as per the PHP docs:
PHP 5 introduces a destructor concept similar to that of other
object-oriented languages, such as C++. The destructor method will be
called as soon as there are no other references to a particular
object, or in any order during the shutdown sequence.
In regards to your question, the method __destruct() might not be called because the static class var private static $factory is never being nulled. Therefore, the class always has a reference to "itself" preventing __destruct() from being called.
I hope this helps!
Related
I am refactoring a (procedural) PHP Library I wrote a while back into a lightweight OOP framework. I'm getting caught up with trying to pass a PDO object to be used in a class. Here's what I've got so far.
Config.php
<?php
class Config {
// Database Variables
private $db_type;
private $db_host;
private $db_user;
private $db_pass;
private $db_name;
private $db_path; // for sqlite database path
private $db_char; // charset
// Site Variables
private $s_protocol;
private $s_subdomain;
private $s_domain;
private $s_tld;
private $s_dir;
private $s_name;
private $s_description;
private $s_path;
private $s_visibility;
private $s_pipe;
private $s_apps;
private $s_hooks;
private $s_blocks;
private $s_assets;
// User Default
private $u_groupid;
public function __construct($config) {
$this->set($config);
}
public function set($config) {
if (!empty($config) && is_array($config)) {
foreach ($config as $k => $v) {
if (property_exists(get_class($this), $k)) {
$this->$k = $v;
}
}
return true;
}
else { return false; }
}
public function get($config) {
if (!empty($config)) {
return $this->$config;
}
}
public function domain() {
return $this->get('s_protocol') .'://'. $this->get('s_domain') . $this->get('s_tld') .'/'. $this->get('s_dir');
}
}
?>
Database.php
<?php
class Database extends PDO {
private $config;
public function __construct($config) {
$this->config = $config;
switch($this->config->get('db_type')) {
case 'mysql':
case 'pgsql':
try {
return new PDO(
$this->config->get('db_type') .':dbname='. $this->config->get('db_name') .';host='. $this->config->get('db_host'),
$this->config->get('db_user'),
$this->config->get('db_pass')
);
}
catch(PDOException $e) {
die($e->getMessage());
}
break;
case 'sqlite':
try {
return new PDO($this->config->get('db_type') .':'. $this->config->get('db_path'));
}
catch(PDOException $e) {
die($e->getMessage());
}
break;
case 'firebird':
try {
return new PDO(
$this->config->get('db_type') .':dbname='. $this->config->get('db_host') .':'. $this->config->get('db_path'),
$this->config->get('db_user'),
$this->config->get('db_pass')
);
}
catch(PDOException $e) {
die($e->getMessage());
}
break;
case 'informix':
try {
return new PDO(
$this->config->get('db_type') .':DSN='. $this->config->get('db_name'),
$this->config->get('db_user'),
$this->config->get('db_pass')
);
}
catch(PDOException $e) {
die($e->getMessage());
}
break;
case 'oracle':
try {
return new PDO(
'OCI:dbname='. $this->config->get('db_name') .';charset='. $this->config->get('db_char'),
$this->config->get('db_user'),
$this->config->get('db_pass')
);
}
catch(PDOException $e) {
die($e->getMessage());
}
break;
}
}
}
?>
Auth.php
<?php
class Auth {
// Set Database object
protected $db;
// User fields in users table
private $id;
private $email;
private $password;
private $firstname;
private $lastname;
private $displayname;
private $groupid;
private $ip;
private $created;
private $updated;
private $cookie;
private $sessionid;
private $lastlogin;
private $token;
private $active;
public function __construct($dbh) {
$this->db = $dbh;
}
public function add($params) {
$sql = '
INSERT INTO
`users` (
';
$cols = array_keys($params);
$col_string = implode(', ', $cols);
$sql .= $col_string .'
)
VALUES (
';
array_walk($cols, function(&$v, $k) { $v = ':'. $v; });
$col_string = implode(', ', $cols);
$sql .= $col_string .'
)
';
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
}
public function remove($params) {
}
public function update($params) {
}
public function get($params) {
}
protected function set($params) {
if (!empty($params) && is_array($params)) {
foreach ($params as $k => $v) {
if (property_exists(get_class($this), $k)) {
$this->$k = $v;
}
}
return true;
}
else { return false; }
}
}
?>
init.php
<?php
session_start();
$params = array(
'db_type' => 'mysql',
'db_host' => '127.0.0.1',
'db_user' => 'user',
'db_pass' => 'password',
'db_name' => 'database',
'u_groupid' => 4
);
require_once('Config.php'); $c = new Config($params);
require_once('Database.php'); $db = new Database($c);
require_once('Auth.php'); $u = new Auth($db);
$user = array(
'email' => 'newperson#email.com',
'password' => md5('password'),
'firstname' => 'Jeff',
'lastname' => 'Wilson',
'displayname' => 'Jeff Wilson',
'groupid' => $c->get('u_groupid'),
'ip' => $_SERVER['REMOTE_ADDR'],
'created' => date('Y-m-d H:i:s'),
'sessionid' => session_id(),
'active' => 1,
);
$u->add($user);
?>
PHP Fatal error: Call to a member function execute() on a non-object in Auth.php on line 46
This is line 46:
$stmt->execute($params);
As far as I know I'm passing the PDO object to the Auth class correctly. It shouldn't say it's a non-object. Can anyone else see what's wrong here?
The constructor in the Database class is returning a value (a PDO object). The __construct() function should not explicitly return a value. Since your Database class extends PDO, call the parent constructor instead:
parent::__construct(
$this->config->get('db_type') .':dbname='. $this->config->get('db_name') .';host='. $this->config->get('db_host'),
$this->config->get('db_user'),
$this->config->get('db_pass')
);
Unless the pdo instance is set explicitly to use exceptions for error reporting you have to check the return value of PDO::prepare
$stmt = $this->db->prepare($sql);
if ( !$stmt ) {
// prepare failed
// the array returned by $this->db->errorinfo() most likely contains more info about the error
// don't send it unconditionally,directly to the browser, see https://www.owasp.org/index.php/Top_10_2013-A6-Sensitive_Data_Exposure
}
else {
$result = $stmt->execute($params);
if ( !$result ) {
// not ok
}
else {
// ok
}
}
edit: I can leave out the first part of my answer, since Alex Ivey already wrote it. ;-)
Just image behind the scene php is doing something like
function __internal_newDatabase() {
// just image the parser/compiler creates this function
// from your class defintion
$instance = array(
'properties'=>array('config'=>null),
'methods'=>array('beginTransaction'=>PDO::beginTransaction, 'prepare'=>PDO::prepare, ...)
);
// some magic function that calls a method and "replaces" $this by the second parameter
invoke(Database::__construct, $instance);
return $instance;
}
and when your script contains new Database instead it calls __internal_newDatabase(). That's (ooooversimplified) what happens and therefore you can not just "change" the instance within your constructor "method" by returning a different instance. Your constructor is supposed to make this instance fly (or bail out by throwing an exception).
Your class Database is derived from PDO, i.e. it is supposed to behave as a PDO. In other languages that implies that the/a base class' constructor must be called. PHP doesn't enforce that. But in this case leaves your Database instance unusable. You have to explcitily call the parent's constructor as Alex's answer shows.
But there are other issues with this class. (First a confession: I'm biased as can be against class Database. In virtually all in all cases it's just wrong and therfore automagically raises a red flag for me)
Foremost: Given its name and the way you use it, it's superfluous. It's just a configuration detail not a class derived from PDO. More likely it would be a factory and/or something within an IoC container (if you use that).
On the other hand it might not be just a configuration detail but might (and probably will) cause different implementions for different databases. PDO is not a database abstraction, just a unified access layer.
Your class Auth.php doesn't care about the concrete sql dialect used - and this particular query will most likely work for all database systems supported by PDO. But there will sooner or later be queries that have to be customized for the different RDBMSs. And then your base class would probably be called something like DB_Adapter and there would be MySQL_Adapter extends DB_Adapter and so on....
Add this method to your Database class
public function getConnection() {
return new PDO(
$this->config->get('db_type') .':dbname='. $this->config->get('db_name') .';host='. $this->config->get('db_host'),
$this->config->get('db_user'),
$this->config->get('db_pass')
);
}
call prepare statement like this:
$conn = $this->db->getConnection();
$stmt = $conn->prepare($sql);
Your $conn has to be PDO object in this case
The main problem here is while $db = new Database($c); seems to be fine at the first glance, calling $db->prepare is not good because $db is instance of Database, but has to be instance of PDO
One of the ways to improve a bit connection handling would be:
In your Database class to have a private $conn for connection
class Database extends PDO {
private $config;
private $conn;
public function __construct($config) {
$this->config = $config;
switch($this->config->get('db_type')) {
case 'mysql':
case 'pgsql':
try {
$this->conn = new PDO(
$this->config->get('db_type') . ':dbname=' . $this->config->get('db_name') . ';host=' . $this->config->get('db_host'),
$this->config->get('db_user'),
$this->config->get('db_pass')
);
} catch(PDOException $e) {
die($e->getMessage());
}
break;
// ...
}
}
THEN in the same class new method to return connection:
public function getConnection() {
return $this->conn;
}
AND FINALLY call it:
$this->db->getConnection()->prepare($sql)
This question already has answers here:
PHP parse/syntax errors; and how to solve them
(20 answers)
Closed 7 years ago.
Hi i am using PDO DB class to connect to database. But i really wonder if i am doing it correct or not. All connection set up is fine but i get error when i run a query
My Directory Structure is
/root
/dbops <-- Directory contains `config.php` -->
/dbfunctions <-- Directory contains `DBclass.php` & `DBFuncts.php` -->
Now contents of config.php are:
define( 'DB_HOST', 'localhost' );
define( 'DB_USERNAME', 'root');
define( 'DB_PASSWORD', '');
define( 'DB_NAME', 'testDB');
define('DB_CHAR', 'utf8');
function __autoload($class){
$parts = explode('__', $class);
$path = implode(DIRECTORY_SEPARATOR,$parts);
require_once $path . '.php';
}
DBclass.php contains:
class dbdunctions__DBclass{
public $instance = null;
public function __construct() {}
final private function __clone() {}
public static function instance()
{
if (self::$instance === null)
{
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => TRUE,
PDO::ATTR_STATEMENT_CLASS => array('myPDOStatement'),
);
$dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME.';
charset='.DB_CHAR;
self::$instance = new PDO($dsn, DB_USERNAME, DB_PASSWORD,
$opt);
}
return self::$instance;
}
public static function __callStatic($method, $args) {
return call_user_func_array(array(self::instance(), $method), $args);
}
}
class myPDOStatement extends PDOStatement
{
function execute($data = array())
{
parent::execute($data);
return $this;
}
}
DBFuncts.php contains below:
class dbfunctions__DBFuncts
{
protected $_con;
public function __construct()
{
$db = new dbfunctions__DBclass();
$this->_con = $db->con;
}
function gotodb(array $data){
$result =
$this->_con::instance()->prepare($qry)->execute(array(/*parameters*/));
}
}
Now when query is fired with $result then i get following error
Parse error: syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM) in dbops/dbfunctions/DBFuncts.php on line 12
Please guide. I have already spent 2 hrs on this issue and googling around.
Instead of
$this->_con::instance()
You should be able to just do
$this->_con->instance()->prepare($qry)->execute(array(/*parameters*/));
Not sure if it's a typo for when you put the code in - but I did notice that in the DBclass.php you have class dbdunctions__DBclass - surely this should be class dbfunctions__DBclass() ?
Also there seems to be some other errors in your example code ... But lets tackle them one at a time :)
Try adjusting this way. I have it working on my server with some adjustments. Notably instantiating the connection in the __construct() of the dbdunctions__DBclass() class and assigning $this->_con to the self::$instance (dbdunctions__DBclass::$instance;):
class dbdunctions__DBclass
{
// Make the instance static
public static $instance = null;
public function __construct()
{
// Create the static connection in the construct
$this->init();
}
private function init()
{
if (self::$instance === null) {
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => TRUE,
PDO::ATTR_STATEMENT_CLASS => array('myPDOStatement'),
);
self::$instance = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.'; charset='.DB_CHAR, DB_USERNAME, DB_PASSWORD, $opt);
}
}
final private function __clone()
{
}
public static function __callStatic($method, $args)
{
return call_user_func_array(array(self::instance(), $method), $args);
}
}
class myPDOStatement extends PDOStatement
{
public function execute($data = array())
{
parent::execute($data);
return $this;
}
}
class dbfunctions__DBFuncts
{
protected $_con;
public function __construct()
{
// Create instance of database
$database = new dbdunctions__DBclass();
// Assign the connection to the $this->_con
$this->_con = dbdunctions__DBclass::$instance;
}
public function gotodb($statement = false,$bind = false)
{
// Incase the statement or bind is empty, return 0
if(empty($statement) || empty($bind))
return 0;
// Create the query with method chain
$query = $this ->_con->prepare($statement)
->execute($bind);
// Fetch results
while($row = $query->fetch())
$result[] = $row;
// If results return array else return 0 for consistency
return (!empty($result))? $result : 0;
}
}
// Instantiate
$dbFunc = new dbfunctions__DBFuncts();
// Use whatever you use to return a result here. This statement happens
// to work for my database...but likely not yours
print_r($dbFunc->gotodb("select * from `users` where `ID` = :ID",array(":ID"=>"29")));
class dbfunctions__DBFuncts
{
protected $_con;
public function __construct()
{
$db = new dbfunctions__DBclass();
$this->db = $db;
}
function gotodb(array $data){
$result =
$stmt = $this->db->prepare($qry);
$stmt->execute(array(/*parameters*/));
}
The PDO object gets created then made into a "member object". The gotodb object uses the "member object" PDO instance. Below is a sample of code from a site I'm working on which should help explain it better:
try {
$sql="
SELECT
id
, name
, description
FROM
ue_bug_project
";
// $stmt objected created by preparing the SQL query for execution, using the PDO object, which in this case is $this->db
$stmt = $this->db->prepare($sql);
// The execute method of the $stmt object is run executing the query, in this case no query data is bound as there is no user submitted data being used
$stmt->execute();
// The result set is grabbed in one hit and placed into the projects array (I really should have set up the $projects variable as an empty array beforehand)
$projects = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $projects;
}
// If the query fails with an error, the catch block is run, in this case i log the error.
catch (PDOException $e) {
error_log('Error when getting the list of projects!');
error_log(' Query with error: '.$sql);
error_log(' Reason given:'.$e->getMessage()."\n");
return false;
}
}
From the looks of your code there's probably no real need to place your own wrapper around the PDO class
here is my code
pdo.php
class Connection {
public function __construct() {
$this->connect ($db);
}
private function connect($db) {
try {
if (! $db){
$this->db = new PDO ( 'mysql:host=localhost;dbname=Shopping;charset=utf8', 'xxxx', 'xxxxx' );
echo 'Connected';
return $this->db;
}
catch ( PDOException $conError ) {
echo 'failed to connect DB' . $conError->getMessage ();
}
}
}
product.php
class ProductInsert extends Connection { //here my function is called multiple times
function __construct() {
parent::__construct($db);
}
public function prdInsert(.....)
{ ........}
here my problem is database connection is opened multiple time. when ever i am calling the productInsert() then database connection is opened how i can prevent this
Do not extend your application class from database class.
This is your main problem.
They are too different classes having nothing in common.
So you have to just use your db object as a property.
Connection class is also useless at the moment, as it's just a leaky disguise for the PDO.
So, just create raw PDO object and then pass it in the constructor of product
class ProductInsert
{
function __construct(PDO $db)
{
$this->db = $db;
}
public function prdInsert(.....)
}
And for goodness sake, learn to indent your code.
class Connection {
public function __construct($db) {
return $this->connect($db);
}
private function connect($db) {
try {
if (! $db){
$db = new PDO ( 'mysql:host=localhost;dbname=Shopping;charset=utf8', 'xxxx', 'xxxxx' );
echo 'new connection';
}
return $db;
}
catch ( PDOException $conError ) {
echo 'failed to connect DB' . $conError->getMessage ();
}
}
}
here is the solution
pdo.php
class Connection {
// Declare instance
private static $instance = NULL;
// the constructor is set to private so so nobody can create a new instance using new
private function __construct() {
// maybe set the db name here later
}
// Return DB instance or create intitial connection #return object (PDO) #access public
public static function getInstance() {
if (! self::$instance) {
self::$instance = new PDO ( 'mysql:host=localhost;dbname=Shopping;charset=utf8', 'root', 'vss0ftech' );
self::$instance->setAttribute ( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
echo 'connected';
} else
echo 'connection is already existed';
return self::$instance;
}
// Like the constructor, we make __clone private so nobody can clone the instance
PRIVATE FUNCTION __CLONE() {
}
}
product.php
here we can call the method as like this
class ProductInsert {
public function prdInsert(.....) {
$result_By_Vendor_And_Title = Connection::getInstance ()->query ( "select * from........)
}
}
In PHP, I have following Singleton Database Class:
class Database
{
private static $instance;
private function __construct()
{
self::$instance = new mysqli('localhost', 'root', 'Matthias', 'financecontrol', '3307');
if (!self::$instance) {
throw new Exception('Could not connect to database in function __construct.');
}
}
public static function getInstance()
{
if (!self::$instance) {
self::$instance = new Database();
}
return self::$instance;
}
}
Whenever I try to perform a query on the database in another PHP file, for example to check whether a user already exists:
function userExists($username)
{
try {
$connection = Database::getInstance();
$result = $connection->query("select * from user where username='$username'");
if (!$result) {
throw new Exception("Connection to database failed in function userExists.");
}
if ($result->num_rows > 0) {
return true;
} else {
return false;
}
} catch (Exception $ex) {
$errorPager = new ErrorpageGenerator();
$errorPager->generateErrorPage($ex->getMessage());
return false;
}
}
I get an error message "PHP Fatal error: Call to undefined method Database::query() in User.php on line 44"
I've tried adding a query function in the Database class, but that did not seem to fix the problem. Any ideas? Thanks
You have to add this method of course. But you cannot assign Database() and the mySQLi object to m_pInstance
so do:
class Database
{
private static $conn;
// ...
public function __construct()
{
self::$conn = new mysqli('localhost', 'root', 'root', 'database', '3307');
//...
and then
public function query($sql)
{
return self::$conn->query($sql);
// or
return mysqli_query(self::$conn, $sql);
}
EDIT
Working code:
class Database
{
private static $instance = null;
private static $conn;
private function __construct()
{
self::$conn = new mysqli('localhost', 'root', 'root', 'database', '3307');
}
public static function getInstance()
{
if (self::$instance == null) {
self::$instance = new Database();
}
return self::$instance;
}
public function query($sql)
{
return self::$conn->query($sql);
}
}
You get this error, because Database::$m_pInstance is contains an instance of Database class and not instance of MySQLi. You have created a "conflict" between to parts of the code:
public static function getInstance()
{
if (!self::$m_pInstance) {
self::$m_pInstance = new Database(); // << PROBLEM
}
return self::$m_pInstance;
}
Which overrides what your constructor does:
private function __construct()
{
self::$m_pInstance = new mysqli( /* .. */ ); // PROBLEM
if (!self::$m_pInstance) {
throw new Exception('Could not .. blah');
}
else {
return self::$m_pInstance;
}
}
Even though the constructor assigns self::$m_pInstance the instance of MySQLi object, it gets overridden by self::$instance = new Database(); right after.
Also, in php __constuct() method should not return, ever.
That said, i think is should warn you that singleton is considered to be an anti-patterns, and should be avoided. Your code also has the unintended side-effect, forcing you to have only one database (not connection, the database) available per application.
You might benefit from watching few lectures:
Advanced OO Patterns (slides)
Global State and Singletons
Don't Look For Things!
Your code does not look right.
first, you assign $m_pInstance a new Database instance. But then, in the constructor, you assign it a new mysqli instance. I am unsure how php handles this case, but it seems that it treats it as Database object as indicated by your error message. The Database class however does not have a query method.
So the solution would be to save the mysqli object in a different field and add getters and setters for it or delegate the methods to it.
My first real foray into using PHP OOP and PDO extensively. I have finally gotten the script to work, but as you notice in order to do it I had to move the PDO connect into the login function - originally it was just in the __construct(). I do not want to have to open a new PDO connect and this is sloppy. How can I maintain the same connection throughout the whole class?
<?php
class user{
public $id;
public $name;
public $email;
private $password;
public function __construct() {
$DBH = new PDO("mysql:host=HOST;dbname=DB", "USER", "PASS");
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
public function login($email,$password,$type){
$DBH = new PDO("mysql:host=HOST;dbname=DB", "USER", "PASS");
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$password_hash = sha1($password);
try{
if ($type != "actives") {
throw new Exception("Type Handling Error");
}
$STH = $DBH->query("SELECT id, email, password FROM $type WHERE email='$email' AND password='$password_hash'");
$STH->setFetchMode(PDO::FETCH_ASSOC);
$row_count = $STH->rowCount();
$row = $STH->fetch();
if($row_count == 1){
session_start();
session_regenerate_id();
$_SESSION['id'] == $row[id];
return true;
}
else{
return false;
}
}
catch (Exception $e) {
echo $e->getMessage();
}
}
public function loggout(){
session_destroy();
setcookie(session_name(), session_id(), 1, '/');
}
Make the database handle a private member within the class:
class user
{
public $id;
public $name;
public $email;
private $password;
private $dbh;
public function __construct(PDO $dbh)
{
$this->dbh = $dbh;
}
public function login($email, $password, $type)
{
$dbh = $this->dbh;
...
}
Usage:
$pdo = new PDO("mysql:host=HOST;dbname=DB", "USER", "PASS");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$user = new User($pdo);
Sooner or later, you may need the PDO connection object somewhere else in your code(outside your user object). Therefore,
I would suggest to use one class which will provide static method as below to get the PDO connection object everywhere you want.
class Database{
private static $datasource='mysql:host=HOST dbname=DB';
private static $username='USER';
private static $password='PASS';
private static $db;
//make the constructor private and empty so that no code will create an object of this class.
private function __construct(){}
//the main public function which will return the required PDO object
public static function getDB(){
if(!isset(self::$db)){
try{
self::$db=new PDO(self::$datasoure,self::$username,self::$password);
}
catch(PDOExceptin $e)
{
$error=$e->getMessage(); //variable $error can be used in the database_error.php file
//display database error file.
include('database_error.php');
exit();
}
}
return self::$db;
}
}
Then you can use the static method like below any time you want PDO connection
$conn=Database::getDB();
Use ceejayoz' proposal or add a global function which is responsible for establishing the database connection. The function is written as to connect to the database at most 1 time per HTTP request:
function getPDOConnection() {
// Thanks to the static-specifier, this variable will be initialized only once.
static $conn = new PDO("mysql:host=HOST;dbname=DB", "USER", "PASS");
return $conn;
}
This enables you to maintain the same connection in your whole application (but of course you don't have to use the function everywhere). Basically, this is a very simple application of the Singleton pattern. See the documentation of the static specifier/keyword and try to get familiar with the Singleton pattern.
Add your database connection as a parameter in the constructor, So you when you create a new instance from the user class it automatically runs across the instantiated object
The variable $DBH needs to be a member variable of your class.
Below private $password;, add private $DBH; and you're good to go with deleting the new-connection code from your login function.