为什么父进程的构造仅为第一个实例调用?

时间:2014-10-09 21:36:10

标签: php oop

我有这个代码可能编写得很好或者编写得不好:)。我试图理解为什么当我创建一个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服务器已经消失而无法做任何事情"。 那么它是怎样工作的?为什么不会为新实例调用父实例,或者当我取消设置并重新启动它时?

2 个答案:

答案 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();

哪个更短更明显。