我有这个代码可能编写得很好或者编写得不好:)。我试图理解为什么当我创建一个ojbect的新实例时,即使我取消设置它也不会运行父结构。
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
}
}
以下代码仅记录"数据库连接名为"一次。
1
$site = new Site;
unset($site);
$site = new Site;
2
$site = new Site;
$site = new Site;
3
$site = new Site;
$site_new = new Site;
我希望每次创建新实例时都要调用数据库的原因是因为这是一个cli脚本,可以在while
循环内运行几个小时,如果超过MySQL的wait_timeout {{ 1}}只是因为" MySQL服务器已经消失而无法做任何事情"。
那么它是怎样工作的?为什么不会为新实例调用父实例,或者当我取消设置并重新启动它时?
答案 0 :(得分:1)
这是一个棘手的问题,你正在扩展看似单身的东西。
当您在子类中设置构造函数时,永远不会调用父类的构造函数。
但是在子类的相同构造函数中,您正在初始化您的单例,所以当您调用时:
self::$instance=new $object;
直接调用core
类的构造函数。因为它被设置为单身,所以只会发生一次。
我不建议这样做,单身是伪装的全局变量(让测试变得痛苦......)如果你决定使用它,你不应该扩展它,而是调用你的静态单例数据库实例你需要它的地方(就像你实际上在子类的构造函数中做的那样......)。
最好将实例化数据库对象并将其传递给需要它的对象的构造函数(依赖注入)。
顺便说一下,如果你想在子类中调用父类的构造函数,那么你需要在子元素的构造函数中使用parent::__construct();
。
答案 1 :(得分:0)
core
类是所谓的“单身人士”。它创建了自己的实例,并使其全局可用。单身人士的全部意义在于,必须只有一个实例。
当您实例化$site
或取消设置它,或再次实例化它时,self::$instance
类的core
属性保持不变。那是因为它是一个静态属性,它们不是绑定到一个实例,而是类成员,它们是持久的(当脚本运行时)。
顺便说一句,以下代码过于复杂:
$object= __CLASS__;
self::$instance=new $object;
它也可能是:
self::$instance = new self();
哪个更短更明显。