This is the singleton pattern also named as the singleton class. Its goal is to allow only one object of type singleton. If there is already one and I call it, I'd like it to error out in some way. This won't happen in production but in development. Is there a better way then just saying echo echo "Error:only one connection";
class singleton
{
protected static $_db_pointer = NULL;
private function __construct()
{
$this->_db_pointer = mysql_connect(DB_HOST, DB_USER, DB_PASS);
mysql_select_db(DB_DATABASE);
}
public static function get_instance()
{
if(self::$_db_pointer == NULL)
{
return new self();
}
else
{
echo "Error:only one connection";
}
}
}
Exceptions usually are better.
else
{
throw new Exception("Error:only one connection");
}
You can also use "LogicException", "RuntimeException", and a few others.
Further reading:
http://www.php.net/manual/en/language.exceptions.php
Another approach with singleton class is just to return the object instead of creating a new instance if one exists.
You haven't implemented the singleton pattern correctly. Had you done so, the error condition to which you refer could not exist.
Combining the PHP documentation's singleton example and the original code gives:
class singleton
{
// Hold an instance of the class
private static $instance;
private static $db_pointer;
// A private constructor; prevents direct creation of object
private function __construct() {
$this->_db_pointer = mysql_connect(DB_HOST, DB_USER, DB_PASS);
mysql_select_db(DB_DATABASE);
}
// The singleton method
public static function get_instance()
{
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
public function getDbPointer() {
return self::$db_pointer;
}
// Prevent users to clone the instance
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
}
Related
i want to implement singleton in the data base super class.
but i want to invoke the methods from it on a sub class object
super class:
class Database {
private $conn;
public static $instance;
private function __construct($conn)
{
$this->conn = $conn;
}
public static function getInstance($conn)
{
if (!self::$instance) {
self::$instance = new Database($conn);
}
return self::$instance;
}
}
sub class:
class Article extends Database
{
public function __construct($conn)
{
parent::getInstance($conn);
}
}
--->
$article = new Article($conn);
but $conn property is not getting initialised.
is there any successful way of doing that without calling directly the super class constructor and keeping the superclass singleton design pattern? Thanks
In Singleton, you instantiate the class by calling its static method getInstance() and send parameters to stablish connection to the database, make the connection and assing it to non-static variable $conn:
class Database {
// Private to ensure you can get instance only by the static method
private static $instance;
// $conn is not static
private $conn;
private function __construct()
{
// Declared to avoid non-static instatiation
}
public static function getInstance($host, $user, $pass)
{
if (!self::$instance) {
self::$instance = new self();
// Connect to database
self::$instance->$con = new PDO($host, $user, $pass);
}
return self::$instance;
}
}
__construct() and getInstance() are already defined in parent class, no need to overwrite them
class Article extends Database
{
public function prepare($query)
{
return $this->conn->prepare($query);
}
}
Instantiate the model and start doing something:
$article = Article::getInstance("mysql:host=localhost;dbname=mydatabase;charset=UTF8", 'myuser', 'mypass');
$stmt = $article->prepare('SELECT * FROM sometable');
i had written a chat module and in this module for lowering pressure on database i used singleton design pattern for getting pdo Object.this is my driver class that uses singletone pattern:
class driver {
protected $_servername= "localhost";
protected $_username= "****";
protected $_password= "****";
protected $_dbname= "***";
private static $instance;
private $dbConn;
// The db connection is established in the private constructor.
public function __construct()
{
$this->dbConn = new PDO("mysql:host=$this->_servername;dbname=$this->_dbname", $this->_username, $this->_password);
// set the PDO error mode to exception
$this->dbConn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
public static function getInstance()
{
if(!self::$instance)
{
self::$instance = new driver();
}
return self::$instance;
}
public function getConnection()
{
return $this->dbConn;
}
public function __clone() {
throw new Exception("Can't clone a singleton");
}
}
in chat class in constructor i use this codde to get the instance:
$instance = driver::getInstance();
$conn = $instance->getConnection();
$this->_conn =$conn;
so if i put a code like
echo 123;die();
inside getinstance static method like this:
if(!self::$instance)
{
self::$instance = new driver();
echo 1111;die();
}
it always returns 1111. why static$instance variable not being filled or stay being filled with driver object?
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.
class SingleTon
{
private static $instance;
private function __construct()
{
}
public function getInstance() {
if($instance === null) {
$instance = new SingleTon();
}
return $instance;
}
}
The above code depicts Singleton pattern from this article. http://www.hiteshagrawal.com/php/singleton-class-in-php-5
I did not understand one thing. I load this class in my project, but how would I ever create an object of Singleton initially. Will I call like this Singelton :: getInstance()
Can anyone show me an Singleton class where database connection is established?
An example of how you would implement a Singleton pattern for a database class can be seen below:
class Database implements Singleton {
private static $instance;
private $pdo;
private function __construct() {
$this->pdo = new PDO(
"mysql:host=localhost;dbname=database",
"user",
"password"
);
}
public static function getInstance() {
if(self::$instance === null) {
self::$instance = new Database();
}
return self::$instance->pdo;
}
}
You would make use of the class in the following manner:
$db = Database::getInstance();
// $db is now an instance of PDO
$db->prepare("SELECT ...");
// ...
$db = Database::getInstance();
// $db is the same instance as before
And for reference, the Singleton interface would look like:
interface Singleton {
public static function getInstance();
}
Yes, you have to call using
SingleTon::getInstance();
The first time it will test the private var $instance which is null and so the script will run $instance = new SingleTon();.
For a database class it's the same thing. This is an extract of a class which I use in Zend Framework:
class Application_Model_Database
{
/**
*
* #var Zend_Db_Adapter_Abstract
*/
private static $Db = NULL;
/**
*
* #return Zend_Db_Adapter_Abstract
*/
public static function getDb()
{
if (self::$Db === NULL)
self::$Db = Zend_Db_Table::getDefaultAdapter();
return self::$Db;
}
}
Note: The pattern is Singleton, not SingleTon.
A few corrections to your code. You need to ensure that the getInstance method is 'static', meaning it's a class method not an instance method. You also need to reference the attribute through the 'self' keyword.
Though it's typically not done, you should also override the "__clone()" method, which short circuits cloning of instance.
<?
class Singleton
{
private static $_instance;
private function __construct() { }
private final function __clone() { }
public static function getInstance() {
if(self::$_instance === null) {
self::$_instance = new Singleton();
}
return self::$_instance;
}
}
?>
$mySingleton = Singleton::getInstance();
One thing to not is that if you plan on doing unit testing, using the singleton pattern will cause you some difficulties. See http://sebastian-bergmann.de/archives/882-Testing-Code-That-Uses-Singletons.html
class Database{
private static $link=NULL;
private static $getInitial=NULL;
public static function getInitial() {
if (self::$getInitial == null)
self::$getInitial = new Database();
return self::$getInitial;
}
public function __construct($server = 'localhost', $username = 'root', $password ='tabsquare123', $database = 'cloud_storage') {
self::$link = mysql_connect($server, $username, $password);
mysql_select_db($database,self::$link);
mysql_query("SET CHARACTER SET utf8", self::$link);
mysql_query("SET NAMES 'utf8'", self::$link);
return self::$link;
}
function __destruct(){
mysql_close(self::$link);
}
}
I just upgraded my php form mysql to use mysqli in an object oriented approach. I have reason to believe that this code has bug in it. My goal is to use a singlton pattern to guarantee only one database connection per script execution. $db holds the database link.
Can someone verify the line
return $one->$db->query($query);
the syntax looks off.
class one
{
private static $single = NULL;
public $db = NULL;
public function __construct()
{
$this->db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE);
self::$single=1;
}
public static function make_one()
{
if(self::$single==NULL)
{
return new self();
}
}
}
/*database*/
class database
{
public function __construct()
{
one::make_one();
}
public static function arche_query($query)
{
return $one->$db->query($query);
}
}
Change it to
return one::make_one->db->query($query);
how ever your singleton pattern is not correct
A singleton pattern should create only one instance , in your case its not that case
class one
{
private static $_selfInstace;
public $db;// default is null so no need to assign
public function __construct()
{
$this->db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE);
}
public static function getInstance()
{
if( !(self::$_selfInstace instanceof self) ) {
self::$_selfInstace= new self();
}
return self::$_selfInstace;
}
}
class database
{
public function __construct()
{
}
public static function arche_query($query)
{
return one::getInstance()->db->query($query);
}
}