33

I am going to use mysqli_close($connection) to close the $connection. But Before Closing I need to ensure that the concerned connection is open.

I tried

if($connection)
{
  mysqli_close($connection);
}

But it is not working. Any Solution?

Munib
  • 3,533
  • 9
  • 29
  • 37

8 Answers8

46

This is from PHP.net.

Object oriented style


<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if ($mysqli->connect_errno) {
    printf("Connect failed: %s\n", $mysqli->connect_error);
    exit();
}

/* check if server is alive */
if ($mysqli->ping()) {
    printf ("Our connection is ok!\n");
} else {
    printf ("Error: %s\n", $mysqli->error);
}

/* close connection */
$mysqli->close();
?>

Procedural style


<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* check if server is alive */
if (mysqli_ping($link)) {
    printf ("Our connection is ok!\n");
} else {
    printf ("Error: %s\n", mysqli_error($link));
}

/* close connection */
mysqli_close($link);
?>
Dharman
  • 30,962
  • 25
  • 85
  • 135
user2060451
  • 2,576
  • 3
  • 24
  • 31
  • 9
    If the connection was closed before, it throws: `mysqli::ping(): Couldn't fetch mysqli`. – Leopoldo Sanczyk Jan 16 '17 at 05:24
  • Continuing on Leopoldo's comment, what about if we try-catch a ping, e.g. `try { return $db->ping(); } catch (Throwable) { return false; }`? I suppose `ping()` could theoretically return errors even if the connection is technically up and working? But I'm not sure.. – user966939 Jul 27 '23 at 22:26
13

While some suggest to check for $connection->ping(),$connection->stat() or mysqli_thread_id($connection), the three will throw: 'Couldn't fetch mysqli' if the connection was closed before.

The solution that worked for me was:

if(is_resource($connection) && get_resource_type($connection)==='mysql link'){
    $connection->close(); //Object oriented style
    //mysqli_close($connection); //Procedural style 
}

PS: Checking only if it's a resource could be enough in a controlled context.

Leopoldo Sanczyk
  • 1,529
  • 1
  • 26
  • 28
8

you can check if mysqli server info is set.

$connection = new MySQLi('localhost', 'user', 'pass', 'db');
if(!isset($connection->server_info)){
    echo 'sql connection is closed';
}else{
    $connection -> close();
}
saman koushki
  • 111
  • 1
  • 6
  • 1
    This won't tell you if the connection has been dropped by MySQL server. It will only inform you about the state of mysqli object. – Dharman Oct 16 '21 at 20:41
  • 1
    I am also checking if $connection is set and that $connection->connect_error is not present – Rohit Gupta Jun 27 '22 at 11:57
5

Just don't close it. That would be the best solution ever.

99.9% of time it's perfectly ok to leave the connection alone, PHP will close it for you.

Only if your script has to perform some heavy time consuming task that doesn't involve a database interaction, you may want to close the connection before starting this operation. But in this case you will have the connection deliberately open as there will be no random closures scattered around the code and therefore will be no need to check whether it is closed already. Hence, just close it, in this particular but extremely rare case.

All other time just leave it alone.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
  • 8
    But that Will Cause too Many Connections opened. – Munib May 01 '13 at 14:00
  • 3
    No it won't.... What causes too many connections errors is you not having enough connections for the amount of load being put onto the db. Not not closing them. – Dave May 01 '13 at 14:01
  • 1
    Is it a Professional Approach to Leave the Connections Opened? – Munib May 01 '13 at 14:03
  • Its fine/perfectly acceptible and actually puts less load on the server as you're not having to constantly open and reclose connections instead they're just sat there in the pool until they're needed. – Dave May 01 '13 at 14:05
  • Ok, that's good for me. But I have a confusion. If a Connection is opened and I request one more connection, will this opened connection be used or the new one be opened? – Munib May 01 '13 at 14:08
  • 3
    It doesn't magically stay open. You need to set persistent connections to be on. Otherwise the script will kill the connection at it's end. – Chris Bornhoft May 01 '13 at 14:12
  • Just prepend p: before the server hostname on mysqli to set them to persistant connections. But no it will only open a new connection if a new connection is required otherwise it'll always reuse an existing connection if there's one sat there doing nothing. – Dave May 01 '13 at 14:25
  • @Munib are you asking for the same running script instance or different one? Frankly - is it for the same script you need second connection or another script? – Your Common Sense May 01 '13 at 15:38
  • @YourCommonSense Not on the same script but on some other script – Munib May 01 '13 at 16:07
  • @Munib new connection will be opened. that's how all PHP scripts works. – Your Common Sense May 01 '13 at 16:19
  • This is what I've put together for personal use. Well, a very watered down version at least. http://pastebin.com/8kcs7qbw – Nathan F. Oct 01 '14 at 11:08
  • What causes too many connections is exactly do not close them, this is basic but fatal error that bring a mysql server down – Federico Schiocchet Oct 10 '19 at 16:38
  • 2
    @FedericoSchiocchet your ideas are completely wrong. PHP closes all connections automatically when the script execution is ended. – Your Common Sense Aug 27 '20 at 14:19
4

If you open a connection, it will stay open until it's explicitly closed or the script ends (unless persistent connections is on). Using the code you have should work.

One option is to extend the mysqli class and have a status property called $connected:

class CustomMysqli extends mysqli
{
    protected bool $connected;

    public function __construct($host, $username, $password, $database)
    {
        parent::__construct($host, $username, $password, $database);
        $this->connected = ($this->connect_errno === 0);
    }

    public function close(): void
    {
        if ($this->connected) {
            parent::close();
            $this->connected = false;
        }
    }

    public function isConnected(): bool
    {
        return $this->connected;
    }
}

Checking for the $connected property is a bit overkill, but will ensure the connection is still open.

Chris Bornhoft
  • 4,195
  • 4
  • 37
  • 55
  • why the connection is returned in class constructor ? – Andrei Todorut Feb 15 '18 at 09:25
  • 1
    @AndreiTodorut So that when you connect to a database, you're now able to connect using `$conn = new CustomMysqli(...);` instead – Chris Bornhoft Feb 20 '18 at 01:05
  • Is this tested code? [rhetorical question, the answer is clearly "no"] I don't see any link between the `CustomMysqli` object, and `$conn` - the `mysqli` object. As written, `close` will never get called. (And if it did get called, $conn might not be from the same CustomMysqli - this is a mess. )This code is *not* an example of *extending* class `mysqli` - that would look like `CustomMysqli extends mysqli` and `parent::construct($host, $username, $password, $dbname);` Also, AFAIK, returning a value from a constructor is meaningless - that isn't how constructors work. – ToolmakerSteve Aug 12 '20 at 22:02
  • 1
    @ToolmakerSteve This answer is more than 7 years old. From what I remember back then, there was an issue with _truly_ extending the `mysqli` class, but I could be mistaken. I've updated the answer to a modern approach, though I recommend using `PDO` instead. – Chris Bornhoft Aug 13 '20 at 00:28
  • Thanks - looks good now - the original problem does not exist in this updated code - now you have access to the mysqli `close` via parent inheritance. (Though I haven't tested.) [I'm maintaining legacy code that uses mysqli.] – ToolmakerSteve Aug 25 '20 at 00:44
  • FWIW (not that it matters now): If you weren't able to extend mysqli class, a working version of the original broken approach would have been to make a "proxy class": to *wrap* the created `mysli` object - you would have stored it in a field e.g. `private $mysqli;` and `$this->mysqli = new mysqli ...;` then you would have called `$this->mysqli->close();`. [Sorry, being pedantic now.] – ToolmakerSteve Aug 25 '20 at 00:52
-1

The accepted answer didn't work for me because calling functions on the connection would throw a couldn't fetch mysqli error if it was already closed. I ended up inspecting the mysqli object before and after closing the connection:

// Before calling $connection->close()

object(mysqli)#92 (18) {
  ["affected_rows"]=>
  int(0)
  ["client_info"]=>
  string(14) "mysqlnd 7.4.23"
  ["client_version"]=>
  int(11111)
  ["connect_errno"]=>
  int(0)
  ["connect_error"]=>
  NULL
  ["errno"]=>
  int(0)
  ["error"]=>
  string(0) ""
  ["error_list"]=>
  array(0) {
  }
  ["field_count"]=>
  int(0)
  ["host_info"]=>
  string(73) "host.rds.com via TCP/IP"
  ["info"]=>
  NULL
  ["insert_id"]=>
  int(0)
  ["server_info"]=>
  string(10) "1.1.1-log"
  ["server_version"]=>
  int(11111)
  ["sqlstate"]=>
  string(5) "00000"
  ["protocol_version"]=>
  int(10)
  ["thread_id"]=>
  int(1234567)
  ["warning_count"]=>
  int(0)
}

// After calling $connection->close()

object(mysqli)#92 (3) {
  ["client_version"]=>
  int(11111)
  ["connect_errno"]=>
  int(0)
  ["connect_error"]=>
  NULL
}

Based on that info, I just wrote the following simple function:

private function isClosed() : bool
{
    return !is_int($this->connection->thread_id);
}
ShaneOH
  • 1,454
  • 1
  • 17
  • 29
-2

Check connection errors. mysqli_connect() always returns a MySQLi object.

use this:

$mysqli_connection = new MySQLi('localhost', 'user', 'pass', 'db');
if ($mysqli_connection->connect_error) {
   echo "Not connected, error: " . $mysqli_connection->connect_error;
}
else
{
   echo "Connected.";
}
hamid
  • 852
  • 11
  • 27
-4

Try this:

function close_connection(){
    $thread = $mysqli->thread_id;
    $mysqli->close();
    $mysqli->kill($thread);

}

That will close the connection you opened using object oriented style like this:

$mysqli = new mysqli($db_server, $db_username, $db_password, $db_name);

That's the basic idea, but if you're using the procedural style, I'm sure you'll be able to custom the code as you need.

Hazem_M
  • 549
  • 5
  • 11
  • 1
    The mysqli_thread_id() or $mysqli->thread_id function returns the thread ID for the current connection, so you'll be able to kill this very connection. – Hazem_M Jan 05 '14 at 06:45
  • 2
    Have you tried this code? It appears to throw an exception. `mysqli::kill(): Couldn't fetch mysqli` after closing the connection. – Dustin Graham Apr 25 '16 at 16:18