PHP5 __construct没有调用,没有错误

All of a sudden, a script that was working fine for quite some time has stopped, with no error. I've pinned it down to the __contruct method but cannot understand why it's happening. Simplified version of the code....

<?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
    }
}
?>

The PDO constructor works on its own, in fact nothing I put in the ex1 constructor seems to run and no errors in the logs (set to E_ALL & E_STRICT).

Any ideas?

If, your ex2 class has a constructor on it's own, you should call the parent one from it:

class ex2 extends ex1 {

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

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

Also you have a typo:

somefunc() {}

should be:

function somefunc() {}

The simple rules of inheritance (in terms of constructors) are as follows:

  • If the child class does not have its own constructor, then the parent constructor is used
  • If the child class does have its own constructor, the parent constructor must be called explicitly
  • The contract between the parent and child class applies to the constructor, too

Basically, that means that, applied to your code, the parent constructor should be called automatically. You say the constructor is not being called, so you probably defined a constructor in the child class, in which case, simple add this statement:

parent::__construct();

A couple of examples

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

This will echo 123, because Foo::__construct() is called automatically. However, if we change Bar a bit, then the behaviour changes:

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

So the val property isn't being set. A simple fix, though:

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

All in all, setting properties to an instance of PDO isn't considered the best of ideas. Check out dependency injection, google inversion of control and all those buzz-words.

An alternative approach would be to use lazy-loading getters:

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

This way, the DB connection will be created at the last possible moment, when the code that relies on that connection calls the getDb method...