PHP - pass PDO connection to all functions - php

I have a try catch block that connects via PDO to a database. I would like to be able to reference it in all my functions without having to pass it as a parameter. How would I do this? The mentioned code is:
try {
$database = new PDO('mysql:host=127.0.0.1;dbname=coop1','root','');
$database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e) {
echo $e->getmessage();
die();
}
EDIT:
I created a singleton class (attempt below) that executes the try catch block upon _construct
final class database {
private static $instance = NULL;
private function __construct() {
try {
$database = new PDO('mysql:host=127.0.0.1;dbname=coop1','root','');
$database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo $e->getmessage();
die();
}
}
public static function getInstance() {
static $instance = null;
if (self::$instance === NULL) {
$instance = new database();
}
return $instance;
}
}

Declare it as a static attribute of a singleten class. Than you can access it with
$pdo = Singleton::instance()->getConnection();
Alternatively I can suggest taking a look at MArtin Fowler's relational database mapping pattern. It goes a step further, than centralizing ony the connection itself.
Alternatively Doctirne project has a complete implementation of that: www.doctrine-project.org
final class database {
private static $instance = NULL;
private $pdo; //added private variable for pdo
private function __construct() {
try {
$database = new PDO('mysql:host=127.0.0.1;dbname=coop1','root','');
$database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo $e->getmessage();
die();
}
$this->pdo = $database; //saved the connection into the new variable
}
public static function getInstance() {
static $instance = null;
if (self::$instance === NULL) {
$instance = new database();
}
return $instance;
}
//added a function to get the connection itself
function getConnection(){
return $this->pdo;
}
}
So now you use it:
$pdo = database::getInstance()->getConnection();

Related

How to properly write a database class in php with singleton pattern?

Today I did some modifications into my database class. One of them was to use singleton pattern but I'm not 100% sure if i'm doing it right since I have never done this before.
It seems to work tho but still not sure if it does what's supposed to do.
Here is a sample. What do you think? Any suggestions are welcome :)
<?php
class Database {
protected static $instance;
private static $dsn = DB_TYPE.":host=".DB_HOST.";dbname=".DB_NAME;
private static $username = DB_USER;
private static $password = DB_PASS;
private function __construct() {
try {
self::$instance = new PDO(self::$dsn, self::$username, self::$password);
self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
self::$instance->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch (PDOException $e) {
die($e->getMessage());
}
}
private function __clone() { }
public static function getInstance() {
if(!self::$instance) {
new Database();
}
return self::$instance;
}
public function read($query, $data = [])
{
$DB = Database::getInstance();
$stm = $DB->prepare($query);
if($stm) {
$check = $stm->execute($data);
if($check) {
$result = $stm->fetchAll(PDO::FETCH_OBJ);
}
}
}
if(is_array($result) && count($result) > 0) {
return $result;
}
return false;
}
}
// test
echo '<pre>';
print_r(Database::read("SELECT * FROM table"));

PDO wont connect to the database

I've made a simple Database class to handle my database connections. But it's somehow not working? At first it wasn't working with MySQLi, so i tried PDO – which ain't working either.
I am however eager to make PDO work. I've already googled and searched here at StackOverflow, but without luck.
Here's my class:
class Database
{
// Local
protected $_host = "localhost";
protected $_user = "root";
protected $_pass = "root";
protected $_database = "hs";
protected $_connection;
// Construct
private function __construct()
{
try
{
$this->_connection = new PDO('mysql:host=localhost;dbname=hs', $this->_user, $this->_pass);
$this->_connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e)
{
echo 'ERROR: ' . $e->getMessage();
}
}
public function login($usr, $pwd)
{
echo "hi";
}
}
And here's the execution:
if(isset($_POST['hs_login']))
{
$db = new Database;
$db->login($_POST['hs_username'], $_POST['hs_password']);
}
Thanks in advance! :)
Constructors are always public so change that like so:
class Database
{
// Local
protected $_host = "localhost";
protected $_user = "root";
protected $_pass = "root";
protected $_database = "hs";
protected $_connection;
// Construct
public function __construct()
{
try
{
$this->_connection = new PDO('mysql:host=localhost;dbname=hs', $this->_user, $this->_pass);
$this->_connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e)
{
echo 'ERROR: ' . $e->getMessage();
}
}
public function login($usr, $pwd)
{
echo "hi";
}
}
Also, new Database is a method call so change that like so:
if(isset($_POST['hs_login']))
{
$db = new Database;
$db->login($_POST['hs_username'], $_POST['hs_password']);
}
Just wanted to point out, that there are some cases, when you can use private constructors. One of the practical use of them is with Databases, so it's relevant in your case as well. This design pattern is called Singleton pattern, and it relies on static method calls. You don't have to instantiate the class, as instantiation is handled by the class itself. I've put together an example:
<?php
class Database {
private static $instance = null;
private $db;
private static $last_result;
private function __construct() {
try {
$pdo_param = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
);
$this->db = new PDO("mysql:host=YOUR_HOSTNAME;dbname=YOUR_DBNAME", "YOUR_USERNAME", "YOUR_PASSWORD", $pdo_param);
}
catch (PDOException $e) {
die($e->getMessage());
}
}
private static function getInstance() {
if (self::$instance == null) {
self::$instance = new self();
}
return self::$instance;
}
public static function query($sql) {
try {
$instance = self::getInstance();
$stmt = $instance->db->prepare($sql);
$stmt->execute();
self::$last_result = $stmt->fetchAll();
return self::$last_result;
}
catch (PDOException $e) {
die($e->getMessage());
}
}
public static function prepare($sql, $params) {
try {
$instance = self::getInstance();
$stmt = $instance->db->prepare($sql);
$stmt->execute($params);
self::$last_result = $stmt->fetchAll();
return self::$last_result;
}
catch (PDOException $e) {
die($e->getMessage());
}
}
}
$users = Database::query("SELECT * FROM users");
$filtered_users = Database::prepare("SELECT * FROM users WHERE username = :username", array(":username" => "john_doe"));
?>
<pre><?php
print_r($users);
print_r($filtered_users);
?></pre>
Singleton design pattern is really useful when you want to make sure, that there's ONLY ONE instance of a class in any given time.

Unable to use PDO methods when using DB class

Hey guys I'm doing this wrong again I'm sure, but I'm trying to instantiate a PDO database
handler from my class Database from the file class.database.php inside my class AdminSession
from class.admin.php, somethings a bit screwy with my dependancy injection, and it is not
allowing me to use PDO's methods corretly; like fetch(), prepare() etcetra.
the class.database.php file
class Database
{
public $db; // handle of the db connection
private static $dsn="mysql:host=server2.com;dbname=database";
private static $user="user";
private static $pass="pass";
private static $instance;
public function __construct ()
{
$this->db = new PDO(self::$dsn,self::$user,self::$pass,$self::$opts);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->db->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
switch($_SERVER['ENVIRONMENT']) {
case 'staging':
self::$dsn="mysql:host=server1.com;dbname=database";
self::$user="user";
self::$pass="pass";
break;
default:
self::$dsn="mysql:host=server2.com;dbname=database";
self::$user="user";
self::$pass="pass";
}
}
public static function getInstance()
{
if(!isset(self::$instance))
{
$object= __CLASS__;
self::$instance=new $object;
}
return self::$instance;
}
}
and here's the topmost of my class.admin.php, and a method that is throwing an error.
right now the errors I'm getting
PHP Fatal error: Call to undefined method line 230
If I use $this->db-prepare($sql)
or
PHP Fatal error: Call to a member function prepare() on a non-object line 230
If I use $db-prepare($sql)
require('library/class.database.php');
class AdminSession {
static $abs_path;
public function __construct(Database $db) {
session_start();
self::$abs_path = dirname(dirname(__FILE__));
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$this->post = $_POST; // filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
if(get_magic_quotes_gpc ()) {
//get rid of magic quotes and slashes if present
array_walk_recursive($this->post, array($this, 'stripslash_gpc'));
}
}
$this->get = $_GET; // filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING);
array_walk_recursive($this->get, array($this, 'urldecode'));
}
// other methods
private function checkDB($username, $password) {
$sql = "SELECT * FROM users WHERE username=:username";
try {
$db = Database::getInstance();
$stmt = $db->prepare($sql);
$stmt->bindParam("username", $username);
$stmt->execute();
$user = $stmt->fetchAll(PDO::FETCH_OBJ);
$db = null;
if($user) {
//general return
if(is_object($user[0]) && md5($user[0]->password) == $password) {
return true;
} else {
return false;
}
} else {
return false;
}
} catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
}
You can't put logic into your class definition. Instead, determine the value of these variables within the constructor. The switch will work in a method, but not when defining members.
Edit: I actually feel silly for missing this. The connection was made before the switch statement. I don't know that it'll fix the second set of issues ... but it'll behave properly for the original question now.
class Database
{
public $db; // handle of the db connection
private static $opts = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8');
private static $dsn="mysql:host=server2.com;dbname=database";
private static $user="user";
private static $pass="pass";
private static $instance;
public function __construct ()
{
switch($_SERVER['ENVIRONMENT']) {
case 'staging':
self::$dsn="mysql:host=server1.com;dbname=database";
self::$user="user";
self::$pass="pass";
break;
default:
self::$dsn="mysql:host=server2.com;dbname=database";
self::$user="user";
self::$pass="pass";
}
$this->db = new PDO(self::$dsn,self::$user,self::$pass,$self::$opts);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
public static function getInstance()
{
if(!isset(self::$instance))
{
$object= __CLASS__;
self::$instance=new $object;
}
return self::$instance;
}
}

Establishing database connection in php using singleton class

Can anybody please guide me with a sample code to establish a database connection in php using singleton class.
class DatabaseSingleton
{
// [Singleton]
private static $instance = null;
public static function getInstance()
{
if (!self::$instance)
{
self::$instance = new self();
}
return self::$instance;
}
private function __clone(){}
// [/Singleton]
private $connection = null;
private function __construct()
{
$this->connection = mysql_connect('localhost','root','admin');
if ($this->connection)
{
mysql_select_db('my_database');
}
}
//
// crud operations go here.
//
}
$db = DatabaseSingleton::getInstance();
$db->SomeCRUDOperation();
Something like that perhaps? Very basic, but should give you a starting point.
That's how a singleton-pattern looks like:
<?php
class SingletonClass
{
static private $instance = null;
static public function getInstance()
{
if (null === self::$instance) {
self::$instance = new self;
}
return self::$instance;
}
private function __construct(){}
private function __clone(){}
}
$singletonClass = SingletonClass::getInstance();
Now you can put random functions and parameters in there that handle your DB-stuff. I hope that answers your question.
See the manual for an example on how to implement the Singleton pattern: http://www.php.net/manual/en/language.oop5.patterns.php
Then just establish the database connection in your class constructor.
I use something like this:
class DBConn
{
static private $_db = null; // The same PDO will persist from one call to the next
private function __construct() {} // disallow calling the class via new DBConn
private function __clone() {} // disallow cloning the class
/**
* Establishes a PDO connection if one doesn't exist,
* or simply returns the already existing connection.
* #return PDO A working PDO connection
*/
static public function getConnection()
{
if (self::$_db == null) { // No PDO exists yet, so make one and send it back.
try {
self::$_db = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME, DB_USER, DB_PASS);
} catch (PDOException $e) {
// Use next line for debugging only, remove or comment out before going live.
// echo 'PDO says: ' . $e->getMessage() . '<br />';
// This is all the end user should see if the connection fails.
die('<h1>Sorry. The Database connection is temporarily unavailable.</h1>');
} // end PDO connection try/catch
return self::$_db;
} else { // There is already a PDO, so just send it back.
return self::$_db;
} // end PDO exists if/else
} // end function getConnection
} // end class DBConn
/**
* And you can use it as such in a class
* */
class Post {
public function __construct(){
$this->db = DBConn::getConnection();
}
public function getPosts()
{
try {
/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM posts";
foreach ($this->_dbh->query($sql) as $row) {
var_dump($row);
}
/*** close the database connection ***/
$this->_dbh = null;
} catch (PDOException $e) {
echo $e->getMessage();
}
}
}
I am using something like below
class Database
{
private $_connection;
private static $_instance; //The single instance
private $_host = "HOST";
private $_username = "USERNAME";
private $_password = "PASSWORd";
private $_database = "DATABASE";
public static function getInstance() {
if(!self::$_instance) { // If no instance then make one
self::$_instance = new self();
}
return self::$_instance;
}
private function __construct() {
$this->_connection = new mysqli($this->_host, $this->_username,
$this->_password, $this->_database);
// Error handling
if(mysqli_connect_error()) {
trigger_error("Failed to conencto to MySQL: " . mysqli_connect_error(),
E_USER_ERROR);
}
}
// Magic method clone is for prevent duplication of connection
private function __clone() { }
public function getConnection() {
return $this->_connection;
}
}
$db = Database::getInstance();
$mysqli = $db->getConnection();
$sql_query = "SELECT foo FROM etc";
$result = $mysqli->query($sql_query);

PDO using singleton stored as class properity

OOP drives me crazy. I can't move PDO to work. Here's my DB class:
class DB extends PDO
{
public function &instance($dsn, $username = null, $password = null, $driver_options = array())
{
static $instance = null;
if($instance === null)
{
try
{
$instance = new self($dsn, $username, $password, $driver_options);
}
catch(PDOException $e)
{
throw new DBException($e->getMessage());
}
}
return $instance;
}
}
It's okay when i do something like this:
try
{
$db = new DB(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASS);
}
catch(DBException $e)
{
echo $e->getMessage();
}
But this:
try
{
$db = DB::instance(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASS);
}
catch(DBException $e)
{
echo $e->getMessage();
}
Does nothing. I mean, even when I use wrong password/username, I don't get any exception.
Second thing - I have class which is "heart" of my site:
class Core
{
static private $instance;
public $db;
public function __construct()
{
if(!self::$instance)
{
$this->db = DB::instance(DB_TYPE.':hpost='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASS);
}
return self::$instance;
}
private function __clone() { }
}
I've tried to use "new DB" inside class, but this:
$r = $core->db->query("SELECT * FROM me_config");
print_r($r->fetch());
Return nothing.
$sql = "SELECT * FROM me_config";
print_r($core->db->query($sql));
I get:
PDOStatement Object ( [queryString] => SELECT * FROM me_config )
I'm really confused, what am I doing wrong?
Edit:
Ok, now I've got object as properity, however I still can't use query/exec.
Edit2:
I'm so dumb... The table doesn't have any records (only default values)
Try public static function &instance.

Categories