PHP5 __construct没有调用,没有错误

时间:2014-07-14 11:01:57

标签: php constructor php-5.3

突然之间,一段时间运行良好的脚本停止了,没有错误。我已将其固定到__contruct方法,但无法理解为什么会发生这种情况。简化版的代码......

<?php
class ex1 {
    protected $dbh;
    function __construct(){
        $this->dbh = new PDO('mysql:host=localhost;dbname=db', 'user', 'pw', array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
    }
}
?>


<?php
include('ex1.class.php');
class ex2 extends ex1 {
    somefunc(){
        is_object($this->dbh); // = FALSE
    }
}
?>

PDO构造函数独立工作,实际上我在ex1构造函数中的任何内容似乎都没有运行,日志中没有错误(设置为E_ALL和E_STRICT)。

有什么想法吗?

2 个答案:

答案 0 :(得分:4)

简单的继承规则(就构造函数而言)如下:

  • 如果子类没有自己的构造函数,则使用父构造函数
  • 如果子类 具有自己的构造函数,则必须显式调用父构造函数
  • 父类和子类之间的契约也适用于构造函数

基本上,这意味着,应用于您的代码,应该自动调用父构造函数。你说构造函数没有被调用,所以你可能在子类中定义了一个构造函数,在这种情况下,简单地添加这个语句:

parent::__construct();

几个例子

class Foo
{
    protected $val = null;
    public function __construct()
    {
        $this->val = 123;
    }
}
class Bar extends Foo
{
    public function test()
    {
        return $this->val;
    }
}
$b = new Bar();
echo $b->test();

这将回显123,因为Foo::__construct()会自动调用。但是,如果我们稍微更改Bar,则行为会发生变化:

class Bar extends Foo
{
    protected $another = null;
    public function __construct()
    {
        $this->another = __METHOD__;
    }
    public function test()
    {
        return $this->val;
    }
}
$b = new Bar();
var_dump($b->test());//null

因此val属性未被设置。但是,这是一个简单的解决方法:

class Bar extends Foo
{
    protected $another = null;
    public function __construct()
    {
        $this->another = __METHOD__;
        parent::__construct();//call here, explicitly
    }
    public function test()
    {
        return $this->val;
    }
    public function getMethod()
    {
        return $this->another;
    }
}
$b = new Bar();
var_dump($b->test());//123
echo $b->getMethod();//echoes Bar::__construct

总而言之,将属性设置为PDO的实例并不是最好的创意。查看依赖注入,谷歌控制反转以及所有这些流行语。

另一种方法是使用延迟加载的getter:

class Foo
{
    $this->db = null;
    protected function getDb()
    {
        if ($this->db === null)
            $this->db = new PDO();//create when needed
        return $this->db;
    }
}

这样,当依赖于该连接的代码调用getDb方法时,将在最后一刻创建数据库连接...

答案 1 :(得分:2)

如果你的ex2类有自己的构造函数,你应该从中调用父类:

class ex2 extends ex1 {

    function __contruct() {
        /* ex2::__construct() code here */
        parent::__construct();
    }

    function somefunc() {
        is_object($this->dbh);
    }
}

你也有错字:

somefunc() {}

应该是:

function somefunc() {}