Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
956 views
in Technique[技术] by (71.8m points)

database - PHP pdo instance as private static property

I'm attempting to design my website based on OOP, but I'm having trouble with how to design the database connection. Currently, I'm creating a private static PDO object in an abstract class, Connector. Obviously, anything that needs to interact with the database will extend this class. I've been flipping back and forth on how to make sure that there is only ever one connection, or PDO object, in a script because some pages will need more than one class that extends Connector. Many people seem to recommend a Singleton pattern for this purpose, but the way I currently do it seems to accomplish the same thing.

Here's my current code.

abstract class Connector
{
    private static $dbh;

    public function __construct()
    {
        try
        {
            self::$dbh = new PDO(...);
            self::$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
        catch(PDOException $e)
        {
            die($e->getMessage());
        }
    }

    public function getDB()
    {
        return self::$dbh;
    }
}

Then any subclasses would use it like this.

class Subclass extends Connector
{
    public function interactWithDB()
    {
        $stmt = $this->getDB()->prepare(...);
        // etc...
    }
}

Theoretically, each instance of a subclass should always be accessing the same PDO instance, I think. Does this code actually make sense and or am I misunderstanding static properties somehow? Is it bad design/practice and or does Singleton have more advantages?

Comment if something's not clear, thanks!

EDIT:

The Connector class wasn't meant to exist just to hold the PDO object. It's destructor closes the connection(makes it null) and it contains functions such isValueTaken, which checks if a value is already in the database. It has the following abstract functions

abstract function retrieveData();
abstract function setData();

For example I have a User class that extends Connector. It's defines setData() to register a user in the database. I don't know if this makes a difference to the response.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Obviously, anything that needs to interact with the database will extend this class.

This really makes no sense from an OOP perspective. When some class extends another class that implies an "is a" relationship. If you go this route you are going to have a hard time not violating OCP which is one of the letters in SOLID.

I've been flipping back and forth on how to make sure that there is only ever one connection, or PDO object, in a script because some pages will need more than one class that extends Connector.

Easy! Just create one instance.

Many people seem to recommend a Singleton pattern for this purpose, but the way I currently do it seems to accomplish the same thing.

Many people like that have no clue about OOP principles. Using an singleton just introduces a "fancy" global instance / state.

Does this code actually make sense and or am I misunderstanding static properties somehow?

To be honest it is more a misunderstanding of OOP.

Is it bad design/practice and or does Singleton have more advantages?

See above.


What you should do (in OOP) is inject the database connection into the classes that need it. This makes your code loosely coupled which in turn makes your code better maintainable, testable, debuggable and flexible.

Also I don't really see why you need to create a database class for a pdo connection, because the PDO API itself is already OOP. So unless you have a real reason to write a adapter (can be the case, because there are some) for PDO I would just drop it.

My €0.02

--

In response to your edit:

The Connector class wasn't meant to exist just to hold the PDO object. It's destructor closes the connection(makes it null).

There is often no need at all to close the connection. The connection will automatically be closed once the request is handled (unless we are talking about a persistent connection).

and it contains functions such isValueTaken, which checks if a value is already in the database. It has the following abstract functions

That sounds like a job for another class.

For example I have a User class that extends Connector. It's defines setData() to register a user in the database. I don't know if this makes a difference to the response.

No my point still stands. There is no need for a user to inherit from a database. Doesn't that sounds strange. A user inheriting from a database (I don't want to meet that person). You should inject the database connection into the User if it is needed.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...