I have this code which might or might not be well written :). I'm trying to understand why when I create a new instance of one ojbect it doesn't run the parent construct even if I unset it.
class core
{
protected $db;
private static $dsn = 'mysql:host=localhost;dbname=tracking';
private static $user = 'root';
private static $pass = 'root';
private static $instance;
public function __construct () {
$this->db = new PDO(self::$dsn,self::$user,self::$pass);
error_log("database connection called");
}
public static function getInstance(){
if(!isset(self::$instance)){
$object= __CLASS__;
self::$instance=new $object;
}
return self::$instance;
}
}
class Site extends core{
function __construct(){
global $argc, $argv;
$this->db_core = core::getInstance();
$this->pdo = $this->db_core->db;
$this->track_id = $argv[1];
error_log("SITE construct called!");
}
function save_to_db(){
//stuff
}
}
The following code will only log "database connection called" once.
1
$site = new Site;
unset($site);
$site = new Site;
2
$site = new Site;
$site = new Site;
3
$site = new Site;
$site_new = new Site;
The reason why I want the database to be called every time I create a new instance is because this is a cli script that could run for hours inside a while
loop and if the wait_timeout from MySQL is exceeded $site->save_to_db()
just won't do anything because "MySQL server has gone away". So how does it work? Why wouldn't the parent's construct be called for new instance or when I unset and start it again?
This is a tricky one, you are extending what looks like a singleton.
As you are setting a constructor in the child class, the constructor of the parent class is never called.
But in the same constructor of the child class, you are initializing your singleton, so when you call:
self::$instance=new $object;
You call the constructor of the core
class directly. And as it is set up as a singleton, that will only happen once.
I would not recommend doing it like that, singletons are global variables in disguise (make testing a pain...) and if you decide to use it like that, you should not extend it, but call your static singleton db instance where you need it (like you are actually doing in the constructor of the child class...).
You would be better off instantiating a database object and pass that around to the constructor of the objects that need it (dependency injection).
By the way, should you ever want to call the constructor of a parent's class in the child class, then you would need to use parent::__construct();
in the child's constructor.
The core
class is a so-called “Singleton”. It creates an instance of itself, and makes it globally available. The whole point of the singleton is that there must only be one instance of it.
When you instantiate $site
or unset it, or instantiate it again, the self::$instance
property of the core
class remains untouched. That's because it's a static property, they are not bound to an instance, but are class members, which are persistent (while the script runs).
By the way, the following code is overcomplicated:
$object= __CLASS__;
self::$instance=new $object;
It could as well be:
self::$instance = new self();
Which is shorter and more obvious.