0

My Database Class in PHP is shown below. Is it considered a best practice to have a destruct function?

<?php
class Database{
    private $host;
    private $username;
    private $password;
    private $database;

    private $conn;

    public function __construct($host, $username, $password, $database){
        $this->host = $host;
        $this->username = $username;
        $this->password = $password;
        $this->database = $database;

        $this->connect();
    }
    public function connect(){
        try{
            
            $this->conn = new PDO('mysql:host=' . $this->host . ';dbname=' . $this->database, $this->username, $this->password);

        } catch(PDOException $e){
            print "Error!: " . $e->getMessage() . "<br/>";
            die();
        }
    }
    public function runSQL($query, $params=null){
        try {
            $statement = $this->conn->prepare($query);
            $statement->execute($params);
            return true;
        } catch (PDOException $e) {
            print "Error" . $e->getMessage();
        }
    }
    
    public function close(){
        $this->conn = null;
    }

    /*
        // is this needed??
        function __destruct() {
            $this->conn->close();
        }

    */
}
?>

My concerns for not needing- and therefore I have excluded it from my scripts- are:

  1. Wouldn't the database connection be closed anyways after the script is run?

  2. If I have several calls to the database in a single script, would closing the connection on one interfere with subsequent calls? Example below:

$db = new Database( [configuration here]);

function one($db) {
    $sql = " ...";
    return $db->runSQL($sql;
}

function two($db) {
    $sql = " ...";
    return $db->runSQL($sql);
}


// this should be fine
$x = one($db);

// if the destruct is in place,
//  wouldn't I get an error here?
$y = two($db);

Everything works fine without the destruct being included, but I'm concerned if this is susceptible to memory leaks.

Thank you in advance :)

user3163139
  • 27
  • 1
  • 5
  • 1
    Connection to DB should be available for all queries that you are going to run. Maybe a singleton object for the entire request. There is no gain in closing it for a query and again re opening for new queries. MySQL's(for example) connection is closed automatically regardless of whether you close it explicitly or not. https://stackoverflow.com/questions/4942596/automatic-db-connection-close-in-php – nice_dev May 21 '21 at 18:07
  • 1
    Close the connection as soon as you do not need it anymore (no more queries!) to give it free for any other applications. Destructors are always called as soon as the instance is released (latest when garbage collection occurs). It is good practice to free your resources, but in OOP that happens automatically and PDO is. So if your code ends, it will be cleaned up. Ergo: You don't need to close it. – Markus Zeller May 21 '21 at 18:16
  • 1
    "wouldn't I get an error here?" No, because the destructor wasn't invoked. If you called `unset($db)` you'd invoke it, however. In that specific code, the variable `$db` is in scope at the global level, so once a function runs it stays in scope. That said, destructors are pretty rare in PHP code. There's definitely use-cases, but they are usually very specific and you'll know when you actually need them. – Chris Haas May 21 '21 at 19:45

1 Answers1

1

Generally, unless you have a specific reason you don't need to define a destructor or explicitly close connections in PHP.

Within the most common use case of PHP, CGI web services, processes only live for the span of a single HTTP request. At the end of of the request all resources are garbage-collected and as a result all connections are implicitly closed as though you had called their respective close().

If, for the sake of example, you are writing a persistent, long-running daemon you may then have a reason to worry about open connections. However, resources that are unset or otherwise go out of scope are eventually garbage collected and any connection resources will be implicitly closed.

If I had to make a strawman argument for destructors, let's say the app needs to talk to a service over a raw TCP socket, and to gracefully close the connection a final command needed to be issued, then I would write a destructor like:

public function __destruct() {
  $this->conn->send("QUIT");
  $this->conn->close();
}

and even in that case it would likely not be a problem for the majority of well-designed services as the connection being closed from the other side is a pretty clear indicator that the session is over.

And none of this is to say that you can't or shouldn't explicitly close connections or write destructors, it's just that in the vast majority of cases it's not making much of a difference one way or the other.

Sammitch
  • 30,782
  • 7
  • 50
  • 77