【问题标题】:PHP5 __construct not called, no errorsPHP5 __construct 没有被调用,没有错误
【发布时间】:2014-07-14 19:19:28
【问题描述】:

突然之间,一个运行了很长时间的脚本停止了,没有任何错误。我已将其归结为 __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)。

有什么想法吗?

【问题讨论】:

  • ex1()没有被它的子ex2()实例化,也没有调用父的构造,所以ex1()构造没有被调用
  • 如果您感到高兴并且知道...语法错误

标签: php constructor php-5.3


【解决方案1】:

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

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

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

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 的实例并不是最好的主意。查看依赖注入、google 控制反转和所有这些流行语。

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

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

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

【讨论】:

    【解决方案2】:

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

    class ex2 extends ex1 {
    
        function __contruct() {
            /* ex2::__construct() code here */
            parent::__construct();
        }
    
        function somefunc() {
            is_object($this->dbh);
        }
    }
    

    还有一个错字:

    somefunc() {}
    

    应该是:

    function somefunc() {}
    

    【讨论】:

    • 只调用父构造函数的空构造函数是多余的。如果构造函数没有被覆盖,那么无论如何都会调用父构造函数
    • @Elias Van Ootegem 你是对的。但我们不知道他在 ex2 类中是否有构造函数,因为这是他的代码的“简化版”
    • @phantom:在此处发表评论后,请阅读那段内容。你是对的,看起来构造函数被覆盖了
    • 父::__construct();修复了它,谢谢大家 :) 奇怪的是,如果没有它,它是如何工作这么长时间的!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-06
    • 1970-01-01
    • 2011-11-15
    • 2011-07-04
    • 2021-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多