I have a class Database.php, which is an abstract Singleton class:
<?php
abstract class Database
{
protected static $_instance;
...
public static function instance()
{
$class = get_called_class();
if (!self::$_instance) {
self::$_instance = new $class();
}
return self::$_instance;
}
}
?>
Other databases extend this class and implement the abstract functions, so that I can change the database I use, while making sure my application still works as long as it uses the functions in this abstraction layer (I have left out the function definitions from the above code).
I have a class PDO, in PDO.php. It extends database and also includes the instance() function identical to the one above, but it does not have it's own $_instance variable.
class PDO extends Database
{
//...
public static function instance()
{
$class = get_called_class();
if (!self::$_instance) {
self::$_instance = new $class();
}
return self::$_instance;
}
}
Originally I thought I wouldn't have to include the instance() function in the PDO class, since it inherits from Database. But I included it because I was getting this error:
Fatal error: Call to undefined method PDO::instance()
The problem is that I'm still getting this error, even with the code above. I don't know if this is related, but there is another strange error I was getting. The type of database I want to use, in this case PDO, is stored in a variable accessible through App::setting('DB'). The Model base class in my MVC framework loads the appropriate database class and stores it in $this->_db. Here is the code for the Model:
<?php
require_once 'Databases/Database.php';
class Model
{
protected $_db;
public function __construct()
{
$database = App::setting('DB'); // 'PDO'
require_once 'Databases/' . $database . '.php';
$this->_db = $database::instance(); // this is what triggers the error
}
}
?>
Now this code was giving me an error that I could not redeclare the PDO class. I searched online, and found that the problem is usually related to using include() instead of require_once(). I checked everywhere and my Autoloader, didn't see any include(). Even with require_once() in the model above, it was still giving me the error (this is the only place I was requiring the PDO class...).
To fix that error, I am using a band-aid solution where I replace the require in the Model constructor with:
if (!class_exists($database)) {
require_once 'Databases/' . $database . '.php';
}
Can anyone explain what is going on here?
class Database extends PDO. Although you should stay away from singletons and use dependency injection where possible.