Class extending PDO - parent::__construct does not work, but creating a new PDO does
Asked Answered
F

3

6

I am trying to write a PDO wrapper but I'm having some problems with the constructor. Ideally, I would like to call the parent's constructor but, for some reason, that is not working. I tried (to test) to check if creating a new PDO and that does work, which I find most confusing.

Here is my code:

class db extends PDO {

    private $dbconn;

    public function __construct() {
        $dsn = 'mysql:dbname=' . MYSQL_DB . ';host=' . MYSQL_HOST;
        $user = MYSQL_USER;
        $pw = MYSQL_PW;
        try {
            $this->dbconn = parent::__construct($dsn, $user, $pw);
            $this->dbconn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            return $this->dbconn;
        }
        catch(PDOException $e) {
            echo 'Connection failed: ' . $e->getMessage();;
        }


    }
}

It works if I replace the parent:: line with $this->dbconn = new PDO($dsn, $user, $pw);

I believe that the "correct/elegant" way to do it is to use the parent:: syntax so I would like to know why that is not working/how I can fix it. Anyone can help?

Thank you!

Faustinafaustine answered 22/11, 2011 at 20:9 Comment(6)
A construct doesn't return anything.Ashcroft
php does not have static constructors, as far I remember. I will check laterAuse
"Returns a PDO object on success." - PDO::__construct() But not when used in a parent sense, 'cause you're sort of already inside that object, so it wouldn't make sense to return an instance to itself.Grishilda
The syntax (new foo())->method() should be legal in the 5.4rc1, though. If I remember rightAuse
Why extend PDO at all? What could you possibly add? Better to use a PDO object as a dependency in your wrapper classMatzo
@Matzo Given that he's trying to store the PDO object in $this->dbconn, I'd guess that what you suggest is what he's actually thinking.Grishilda
D
6

That's not how you use constructors, as they don't return anything. Try the following instead:

public function __construct() {
    $dsn = 'mysql:dbname=' . MYSQL_DB . ';host=' . MYSQL_HOST;
    $user = MYSQL_USER;
    $pw = MYSQL_PW;
    try {
        parent::__construct($dsn, $user, $pw);
        $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
    catch(PDOException $e) {
        echo 'Connection failed: ' . $e->getMessage();;
    }
}

NOTE: You may still run into issues, as your constructor doesn't accept the same arguments as the PDO constructor. One of the tenets of OOP is that of equivalence, as embodied in the Liskov Substitution Principle, which means that the protocol (public API) of a subclass should be a strict superset of its superclass. The reason this is important is that if the subclass has an API that differs from the one presented by the class it inherits from, then it can't be used to substitute for the superclass in all cases.

For example, how would you use your subclass to connect to a PostgreSQL database or use a SQLite file instead of using mysql? The PDO superclass can work with all three, along with other database back ends, by virtue of the fact you can pass a DSN in as an argument, but you can't do that with your subclass.

However, all this is getting into aspects of computer science and is drifting off topic somewhat ;)

Dronski answered 22/11, 2011 at 20:16 Comment(0)
G
5

__construct() doesn't have a return value and when you extend a class your custom one is of the type of the extended one. This means (in your case) an object of db is also an object of PDO

At all

$dsn = 'mysql:dbname=' . MYSQL_DB . ';host=' . MYSQL_HOST;
$user = MYSQL_USER;
$pw = MYSQL_PW;
parent::__construct($dsn, $user, $pw);
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Thats the whole constructor you need

Griz answered 22/11, 2011 at 20:16 Comment(0)
C
2

This example allows me to simplify connection string in my software.

$db = new epdo('MyDataBase');

It also allows for different server, username and password only and if required. Hope this helps:

class epdo extends PDO {
    public function __construct($dbname, $server='127.0.0.1', $username='usernamehere', $password='passwordhere') {
        parent::__construct("mysql:host=$server;dbname=$dbname", $username, $password);
        parent::setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

        // error reporting (only show errors on localhost)
        if( $_SERVER['SERVER_ADDR'] == '127.0.0.1') {
            parent::setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
        } else {
            parent::setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
        }
     }
}
Comeau answered 25/9, 2012 at 11:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.