MySQLi close in destructor fires immediately - php

I've recently been redesigning an archaic PHP application, which had most of it's code in 1000+ line long PHP files for each page. I first started by refactoring much of the code into classes. I recently have been working on database connections, and began writing a class for it. I decided to throw $mysqli->close() into the destructor (I'm using the OO approach).
Unfortunately I've almost immediately ran in to problems with it. Instead of the MySQLi connection closing when the page finishes rendering (or when there are no more references to the DB object), it just immediately closes. I've tested this through writing a simple test:
$db = new DBConnect(); //My abstraction class
$db->getSQL()->query("SELECT 1"); //Query fails. Error message states connection closed.
My destructor looks like this:
public function __destruct() {
$this->mysqli->close();
}
My constructor looks like this:
public function __construct() {
$this->mysqli=new mysqli(\MainConfig::$database['host'], \MainConfig::$database['user'], \MainConfig::$database['pass'], \MainConfig::$database['db']);
if($this->mysqli->connect_error) {
die('Connect error (' . $this->mysqli->connect_errno . ') ' . $this->mysqli->connect_error); //This is not ever fired.
}
}
I know it's not some other bit of code closing the connection, since if I comment out the $this->mysqli->close() line, then the code works as expected. It seems to me that the destructor fires immediately which is not the desired behavior. Am I misunderstanding how they are intended to work?

I was able to reproduce the behavior you described with the code:
<?php
class DestructorTest {
public function getter() {
print "DestructorTest::getter() called\n";
return new CallableTest();
}
public function __destruct() {
print "DestructorTest destructor called\n";
}
}
class CallableTest {
public function method() {
print "CallableTest::method() called\n";
}
}
(new DestructorTest())->getter()->method();
which prints:
DestructorTest::getter() called
DestructorTest destructor called
CallableTest::method() called
The long and the short of it is: A destructor may be called as soon as there are no references to an object. This can even happen in the middle of a line -- in this case, for instance, after DestructorTest:getter() is called, the DestructorTest object is no longer reachable, so it is destroyed.
My advice:
You don't need to close MySQLi handles. They already have an internal destructor which will close them when they are garbage-collected.
In fact: avoid writing destructor methods in general. (This applies to many programming languages, not just PHP.) They are frequently not called when you expect them to be, and have a tendency to cause strange, hard-to-debug behavior.
If you're going to ignore this and write a destructor anyways, then you need to make sure that you don't inadvertently destroy something which you've "leaked" a reference to outside your class. In the case of your code, you've allowed code outside the class to get a reference to your MySQLi handle, but you're destroying that handle as soon as your object goes away -- even if the handle is still being used outside.

Related

How to reuse a MySQLi connection

I've ran into an issue with user already has more than 'max_user_connections' active connections
This happens because I use functions for the website functionality, each function contains a
$mysqli = connect();
Though at the same time, each function closes the mysqli at the end of function
mysqli_close($mysqli);
I do not want to include $mysqli as a parameter of the function, as the function is dynamic and would be tiresome to include it with each function call.
the connect() function just contains:
$mysqli = new mysqli(...);
return $mysqli;
I believe the error is thrown because the function sometimes calls itself for different executions, based on user input and pre-requisites... even though the mysqli is closed at the end of the function...
I'd like to know if there is a way of re-using a $mysqli connection sort of like in a global way...
I'm not sure whether I've explained myself fully so if you need some more information please leave a comment.
The proper way to reuse the same object across multiple functions/classes is to use dependency injection. Together with DI container, it can take care of providing the necessary dependencies to your functions leaving them clean.
The principle of clean code demands that your functions do not have side effects and they only do what their name states. This means that you should never be using globals in your functions as that would be causing side effects. The proper way to provide data without side effects to your function is via parameters. A connection to the database is the data that is required by your function.
If your code will be used as some kind of public library, it's even more reason to keep it clean. A function cannot have surprising behaviour. The best way to reduce surprises is by having a clear function signature. This means that all dependencies are listed as parameters with their correct types, the function cannot take dynamic arguments, and the return type must be clearly specified.
When it comes to mysqli connections (or PDO for that matter which you should prefer over mysqli), the connection should only be opened once during the execution of the script. You should never need to close the connection manually.
Here's an example of clean code. Let's imagine that you need to save bookings in the database. You create a service in your model:
<?php
class BookingService
{
public function __construct(protected mysqli $mysqli)
{
}
public function saveBooking(Booking $booking)
{
$stmt = $this->mysqli->prepare('INSERT INTO bookings (date, surname) VALUES (?,?)');
$stmt->execute([$booking->getDate(), $booking->getSurname()]);
}
}
Then in your controller, you just use your service as a dependency:
class BookingController
{
public function __construct(protected BookingService $bookingService)
{
}
public function index(Request $request)
{
$boooking = new Booking($request->get('date'), $request->get('surname'));
$this->bookingService->saveBooking($boooking);
}
}
Your DI container takes care of instantiating the mysqli and BookingService class. You can only create value objects in your controller. The necessary data is passed via parameters. This makes for a very clean and understandable code. Everyone knows what each function does, there are no surprises and everything has type specified.
There are a number of techniques to instantiate a variable only once. This is an anti-solution. Please do not use solutions listed here!
Static variable
If you only want a variable to be instantiated the first time the function is called, you can use a static variable.
function foo(){
static $mysqli;
if ($mysqli === null) {
$mysqli = connect();
}
// call the same function in recursive mode and the same connection will be reused
foo();
// do not close the connection manually!
}
This is a bad solution because your function fetches the dependency manually. You should not create functions that have side effects or multiple objectives. A function that connects should not be called from within a function that does something else. This leads to nightmarish code, which is the reason why you are having this problem now.
Using singleton
Singletons are bad for testing and for code readability. Anytime you need to change the dependency, you need to change all the places where the singleton is used. For a better explanation of why they are bad see What are drawbacks or disadvantages of singleton pattern?
Using globals
Globals are very bad for code maintainability. They are the bane of programmers since forever. It's precisely the reason why we have encapsulation and dependency injection.
Using a global would be very similar to using a static variable, except that the side effect is now global.
function foo(){
// declare a variable as global.
// this will instantiate the variable to null if it doesn't exist as a global yet
global $mysqli;
// if it's null, connect
if ($mysqli === null) {
$mysqli = connect();
}
// call the same function in recursive mode and the same connection will be reused
foo();
// do not close the connection manually!
// but if you must close the connection, just set the variable back to null
}
Do not use any of the above solutions! These are examples of bad unmaintainable spaghetti code. A programmer's nightmare. This answer is only supposed to be a warning of what not to do!

Where to create and close database connection?

I know we always have to close db connection at the end. Let's I have a class and there is four methods and each consists of db queries. Now my question is
Should I create a connection and close it in every different methods
or create the connection in the constructor of the class? If I create
the connection in the constructor then where will I close it. Because
If I close that in any function no other method can access it.
If I create new connection for every method then no of connections may be very high. Then where will I create and close the function proper way?
If you open it, then you need to close it.
As long as you close the connection, you can close it where you want. It seems like maybe your closing woes are more about the design of the procedures of your program. Just because the database call uses a connection doesn't mean it has to be opened and closed right there with it.
Say you might want to reuse a $mysqli variable that's holding a connection. You can pass that connection to a function and either return it or close it inside. In this way, you can isolate the main activity of the database call in the body of the function without having to worry too much about the opening and closing of everything.
Using that technique, it's possible to reuse a connection for multiple queries, contained each inside their own method. Maybe you would be better off opening a class and passing a $mysqli connection to it, as needed.
This depends on your program and your choices about how it will work.
If you are developing a program, and you're curious about the impact of your opening and closing actions, you can call http://php.net/manual/en/mysqli.stat.php or a similar function. If you are opening many threads and not closing them, then you would see the thread count escalate in the answer from mysqli_stat().
The calls may not close, for example, if you have a poorly designed query that runs away from you; the scope of the connection object should close naturally with the end of the script.
Because of the reference-counting system of php it's not necessary to close the connection, it will be freed automatically (unless you open persistent db links), so it shouldn't cause a headache.
You should open the connection only once btw.
Please take into consider transaction concept. Say for example you methods are being called in a sequence, it makes sense to open a connection and keep it open
If there is delay in call of other methods, i would not advice you to keep connection suspended especially if multiple people are going to access the application
Best way would be to implement classes and extend it to your functional class containing methods. Constructor of the extended class can call to the connection function and the destructor can call to disconnect whenever the object is set to NULL.
Or
As your question states, have two functions in base class having construction and other having destruction.
Call to the constructor function before using your connection and destroy it after using.
Example would be:
class bar{
protected function connect(){
#connect to db
}
protected function disconnect(){
#disconnect db
}
class foo extends bar{
function func1 () {
$this->connect();
#Code
$this->disconnect();
}
function func2() {
$this->connect();
#Code
$this->disconnect();
}
function func3() {
$this->connect();
#Code
$this->disconnect();
}
function func4() {
$this->connect();
#Code
$this->disconnect();
}
?>

Is it a good practice to rely on garbage collector in PHP?

I have two methods:
public function a()
{
$db = new Database();
$db->query ('....');
// $db->close();
}
public function b()
{
$db = new Database();
$db->query ('....');
// $db->close();
}
they called in order:
$obj->a();
$obj->b();
I intentionally commented the close() methods. This Database class has a destruct method:
class Database
{
public function __destruct()
{
$this->close();
}
public function close()
{
}
}
I want automatic close database connections between method calls. To do so, the 100% sure way is to call the Database::close method, but I want to do it automatic and be done when method its over. Is this safe way? Because I dont know when garbage collector actually deletes that $db object. What if its still exits when b() runs? Theoretically, garbage collector do the cleaning ups when he feels like...
EDIT
the database closing is just an example! I want to do something else, but this was a good example, dont focus on the closing itself!!
It is not a good idea to close DB connections after each method call.
Usually people create and keep one connection for all script lifetime.
Of course,I assume there is one DB in your project.
You idea is a bad design example. I would recommend you to review you architecture design.
In my experience, you generally should not close/destroy an object that is reusable until you are finished with it completely, although there are some exceptions.
If you know that you will be calling the process multiple times, then you should not destroy the object until after the last call has been made. An exception to this would be if inside the object, you are working with another object or large amounts of data which need to be forcibly free'd on completion of each loop, then you should destroy only that object which is consuming or potentially consuming a large amount of resources once you have finished that cycle.
As far as the __destruct() function, you should put all the code in there needed to destroy the object. Calling another function from within that object is what we programmers call a cyclic reference where you have the memory of one space pointing back to itself and can cause the garbage collection to fail.
The highest level of control you have over freeing memory from within PHP is to use the unset() command on the object you wish to have destroyed. Using unset() on an object pointer to a class will call that classes __destruct() function.
Executing unset() on an object tells the GAC to give a higher priority when resources are required to cleanup those objects referenced using that command. This is what makes this useful when using memory intensive loops, or poorly written classes within your objects.

How reliable is __destruct?

Are there situations in which this method would not be called?
I'm thinking to store a important variable into a persistent cache just before the cache object gets destroyed. This variable is used many times in the page so I wouldn't like to update the cache with it every time the variable changes...
Let's have a class:
class A {
public function __construct(){
echo "Construct\n";
}
public function __destruct(){
echo "Destruct\n";
}
}
And test code:
$test = new A();
die( "Dead\n"); // Will output Construct; dead; Destruct
$test = new A();
throw new Exception("Blah\n"); // Construct, Fatal error (no destruct)
$test = new A();
require_once( 'invalid_file.php'); // Construct, Fatal error (no destruct)
So basically: there are situations (fatal errors) when destructor won't be called.
Ah and this question has the same answer as this one: When will __destruct not be called in PHP? (+/-)
It is called as soon as there are no more references to that particular object, or during the shutdown sequence. The manual also states destructors are called when scripts are terminated with exit().
Aside from the issue pointed out by TimWolla, I am not aware of any problems with PHP destructors.
It seems there at least was a problem using Windows: https://github.com/WoltLab/WCF/blob/ff7e6ed381f2ccab7f51220f97087921133b2237/wcfsetup/install/files/lib/system/WCF.class.php#L122
I don't know whether this is still relevant.

Php Destructors

Please give me some real life examples when you had to use __destruct in your classes.
Ok, since my last answer apparently didn't hit the mark, let me try this again. There are plenty of resources and examples on the internet for this topic. Doing a bit of searching and browsing other framework's code and you'll see some pretty good examples...
Don't forget that just because PHP will close resources on termination for you doesn't mean that it's bad to explictly close them when you no longer need them (or good to not close them)... It depends on the use case (is it being used right up to the end, or is there one call early on and then not needed again for the rest of execution)...
Now, we know that __destruct is called when the object is destroyed. Logically, what happens if the object is destroyed? Well, it means it's no longer available. So if it has resources open, doesn't it make sense to close those resources as it's being destroyed? Sure, in the average web page, the page is going to terminate shortly after, so letting PHP close them usually isn't terrible. However, what happens if for some reason the script is long-running? Then you have a resource leak. So why not just close everything when you no longer need it (or considering the scope of the destructor, when it's no longer available)?
Here's some examples in real world frameworks:
Lithium's lithium\net\Socket class
Kohana's Memcached Driver
Joomla's FTP Implementation
Zend Frameworks's SMTP Mail Transport Class
CodeIgniter's TTemplate Class
A Tidy Filter Helper for Cake
A Google-Groups Thread about using Destructors For the Symfony Session Class
The interesting thing is that Kohana keeps track of the tags, so that it can delete by "namespace" later (instead of just clearing the cache). So it uses the destructor to flush those changes to the hard storage.
The CodeIgniter class also does something interesting in that it adds debugging output to the output stream in the destructor. I'm not saying this is good, but it's an example of yet another use...
I personally use destructors whenever I have long running processes on my master controller. In the constructor, I check for a pid file. If that file exists (And its process is still running), I throw an exception. If not, I create a file with the current processes id. Then, in the destructor I remove that file. So it's more about cleaning up after itself than just freeing resources...
There is another handy use to generate HTML page
class HTMLgenerator {
function __construct() {
echo "<html><body>";
}
function __destruct() {
echo "</body></html>";
}
}
With this class, you can write
$html = new HTMLgenerator();
echo "Hello, world!";
And the result is
<html><body>Hello, world!</body></html>
For example:
<?php
class Session
{
protected $data = array();
public function __construct()
{
// load session data from database or file
}
// get and set functions
public function __destruct()
{
// store session data in database or file
}
};
This is a good why to use destruct. You prevents reading and writing to a session source all the time and do this only at the start and at the end.
I create a php page what will generate a movie information jpg file. This page will have to gather a few information and run inkscape to convert template (an svg file) to a png before converting to jpg. The svg contain relative links to other image which must be a file. So my page download necessary files into a temporary folder, convert the svg file. At the end, the temporary folder must be deleted.
I put the temporary folder deletion into the destructor. Before there can be many reason the page ends unexpected and the only think I can be sure is that destructor will be call when page exit.
Hope this helps.
A destructor is extremely useful if you use a custom database connector/wrapper.
In the constructor, you can pass the connection information. Because you can use a destructor (rather than a finalizer, etc.,) you can rely on that to close the connection for you. It's more of a convenience, but it certainly is useful.
For example, when PHP decides to explicitly "free" the object (i.e., it is no longer used,) it will call the destructor at that time. This is more useful in the scenario I describe as you're not waiting for the garbage collector to run and call the finalizer.
$0.02
Ian
<?php
class Database
{
private $connection;
private $cache = array();
function __construct([$params])
{
//Connection here
}
//Query
public function query(Query $Query)
{
if($this->is_cached($Query->checksum))
{
return $this->get_cache($Query->checksum);
}
//...
}
public function __destruct()
{
unset($this->connection);
$this->WriteCache();
unset($this->cache);
shutdown_log($this,'Destruction Completed');
}
}
?>
theres an example that should make you understand.
If you use handles returned by fopen() for say, logging, you can use __destruct() to make sure fclose() is called on our resources when your class is destroyed.
You are right, __destruct is mostly unnecessary for the short running php scripts. Database connections, file handles and so on close on script exit or sometimes even earlier if variables run out of scope.
One example i can think of is writing logs to the database. Since we didn't want to fire one query per log entry that gets created somewhere in the script we wrote the "write to db" part in the __destruct of the logging class so when the script ends everything gets inserted into the database at one.
Another example: If you allow a user to upload files the destructor is sometimes a nice places to delete the temp file (in case something goes wrong in the script it at least get cleaned up)
But even for filehandles it can be useful. I've worked on a application that did use the old fopen etc. calls wrapped in objects and when using those on large filetrees php would run out of filehandles sooner or later, so cleaning up while the script was running was not only nice but necessary.
I use APC caching for large numbers of "low level" objects, that otherwise would use excessive memory; and I have a cacheCollection object that handles the reading and writing of those "low level" objects to and from APC during execution of the script. When the script terminates, the objects must be cleared down from APC, so I use the cacheCollection __destruct method to perform that function.
I have used __destruct() in a logging class that wrapped a database connection:
<?php
class anyWrap
{
private $obj,$calls,$log,$hooks;
function anyWrap($obj, $logfile = NULL)
{
if(is_null($logfile))
{
$this->log = dirname(__FILE__) . "/../logs/wrapLog.txt";
}
$this->hooks = array();
$this->dbCalls = 0;
$this->obj = $obj;
}
public function __set($attri, $val) {
$this->obj->$attri = $val;
}
public function __get($attri) {
return $this->obj->$attri;
}
public function __hook($method)
{
$this->hooks[] = $method;
}
public function __call($name,$args)
{
$this->calls++;
if(in_array($name,$this->hooks))
{
file_put_contents($this->log,var_export($args,TRUE)."\r\n",FILE_APPEND);
}
return call_user_func_array(array($this->obj,$name),$args);
}
//On destruction log diagnostics
public function __destruct()
{
unset($this->dbReal);
file_put_contents($this->log,$this->calls."\r\n",FILE_APPEND);
}
}
The script hooks into the database calls and logs the prepare statements, then when the script has run to an end (I don't always know when) it will finally log the number of calls to the database to the file. This way I can see how many times certain functions has been called on the database and plan my optimization accordingly.
If you are creating a view using a PHP script in a MySQL database, you must drop that view at the end of the script. Because if not, the next time that script is executed view will not be created, as there is already a view of similar name in the database. For this purpose you can use destructor.
Here's a rather unusual use case for destructors that I think libraries such as pest are using to combine method chaining with functions or in other words, to achieve fluent interface for functions, Which goes like this:
<?php
class TestCase {
private $message;
private $closure;
private $endingMessage;
public function __construct($message, $closure) {
$this->message = $message;
$this->closure = $closure;
}
public function addEndingMessage($message) {
$this->endingMessage = $message;
return $this;
}
private function getClosure() {
return $this->closure;
}
public function __destruct() {
echo $this->message . ' - ';
$this->getClosure()();
echo $this->endingMessage ? ' - ' . $this->endingMessage : '';
echo "\r\n";
}
}
function it($message, $closure) {
return new TestCase($message, $closure);
}
it('ok nice', function() {
echo 'what to do next?';
});//outputs: ok nice - what to do next?
it('ok fine', function() {
echo 'what should I do?';
})->addEndingMessage('THE END');//outputs: ok fine - what should I do? - THE END

Categories