Where to create and close database connection? - php

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();
}
?>

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!

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 do you efficiently connect to mysql in php without reconnecting on every query

I'm pretty sick of having to rewrite my code every time I learn something new about php (like the fact that mysql connections cannot be passed around in a session as a handle).
How do you implement mysql connection in your projects? A lot of people have proposed "connection pooling", but after reading the manual i'm still lost. It's like: "connection pooling is mysql_pconnect!" - me: "and...? how is that any different in reality? can you pass around a mysql_pconnect in a session? why is this seemingly mysterious aura??"
Let me explain my situation. I have a function called "query1":
function query1($query)
{
$db = new mysql(HOST,USER,PASS,DBNAME);
$result = $db->query($query);
$db->close();
return $result;
}
This is seems like a squanderous and inefficient way of querying a db (especially since you need a mysql handle for functions like mysql_real_escape_string). What is the correct form to do it? Can someone please help me?
Thank you I'd really appreciate a good honest answer.
Normally connections happen once a page load. AKA
class Database{
public function connect()
{
$this->connection = mysql_connect();
}
// This will be called at the end of the script.
public function __destruct()
{
mysql_close($this->connection);
}
public function query($query)
{
return mysql_query($query, $this->connection);
}
}
$database = new Database;
$database->connect();
$database->query("INSERT INTO TABLE (`Name`) VALUES('Chacha')");
Basically, you open the connection in the beginning of the page, close it at the end page. Then, you can make various queries during the page and don't have to do anything to the connection.
You could even do the mysql_connect in the constructor as Erik suggest.
To use the above using global variables (not suggested as it creates global state), you would do something like
Global $db;
$db = new Database;
// ... do startup stuff
function doSomething()
{
Global $db;
$db->query("Do Something");
}
Oh, and no one mentioned you don't have to pass around a parameter. Just connect
mysql_connect();
Then, mysql_query will just use the last connection no matter what the scope is.
mysql_connect();
function doSomething()
{
mysql_query("Do something");
}
Per the comments:
I think you should use mysql_pconnect() instead of mysql_connect(), because mysql_connect() doesn't use connection pooling. – nightcoder
You might want to consider whether you use mysql_connect or mysql_pconnect. However, you should still only connect once per script.
You don't need to connect to the database in every function. You need to connect to the database when the script starts running and save connection object in global state. In any function you can use that connection object to query the database. Your connection object will be recreated for every time script is executed but it will be very fast, because special connection pool is used behind the scene, so connection will be done immediately (matter of microseconds, because actually connection was not even broken, it was saved in connection pool).
Here is the example you asked for:
// this code should be executed on every page/script load:
$adoConn = ADONewConnection(...);
$adoConn->PConnect(...);
// ...
//And then in any place you can just write:
global $adoConn;
$adoConn->ExecuteNonQuery("INSERT INTO test SET Value = 'Hello, world!'");
As for your question "how do I implement connection pool". You don't. It's maintained by the server behind the scene and used if you (or the PHP library for work with PHP) use mysql_pconnect() function.
PS. If you are afraid to keep $adoConn as a global variable (I'm not) then you can create a class with a static property:
class DB
{
public static $adoConn;
}
// ...
DB::$adoConn->ExecuteNonQuery(...);

PHP OOP extending class can't access database connection

Perhaps you can help. I have a main class that creates a MySql connection. Then I extend this class. I wasn't able to access the connection unless I did a parent::__construct(); and recently while doing this I got an error message that I was out of connections.
So how do program this so it doesn't run out of connections and can access the database connection.
class Common
{
var $mysql;
function __construct()
{
$this->mysql=new mysqli($this->dbHOST, $this->dbUSERNAME, $this->dbPASSWORD, $this->dbNAME);
}
}
class Role extends Common {
function __construct()
{
parent::__construct();
}
}
I think there is a fundamental problem with your class structure: You don't need a connection per object, you only need a copy of the connection resource per object.
My preferred way out of this is to create a database handler that has a singleton call. Now it can be called anywhere and it will always return the same connection handler. This is also an excellent way to hide automatic initialization.
The solution was borne out of the realization that a class representing a database row is actually quite different from a class that is a database connection. An app will deal with many many rows but rarely, if ever, will deal with more than one connection. Another way of putting this is the difference between the IS-A and HAS-A definitions: it doesn't make sense to say "a database row class IS-A database connection". It does make sense to say "a datbase row class HAS-A database connection".
Make sure you close the connection when the object is destroyed. That is, add a __destruct() method that closes the connection.
If the Common class is the one that opens the connection in its __construct() method, then it should be the one to close it in its __destruct() method. If you don't define a __destruct() method on the Role class, then it looks like PHP won't call the parent's __destruct() automatically. (I haven't tested this, though.) A simple solution is to add a stub __destruct() method that just calls parent::__destruct().

Connection variable in a class generates error while closing connection

Below is my DB connection class. The problem is that when I try to access the CloseConnection function from my code, it gives error: "Unknown MySQL localhost". I use "dbconnection::CloseConnection" through my other code files. It is successfully opening the connection, but giving error in "$conn".
final class dbconnection
{
private $conn;
//Opens connection for a MySQL DB
public static function OpenConnection()
{
require("../Config/dbconfig.php");
$conn = mysql_connect(DB_HOST,DB_USER,DB_PASSWORD);
mysql_select_db('MyDB');
}
//Closes connection for a MySQL DB
public static function CloseConnection()
{
mysql_close($conn);
}
}
Below is a method in another PHP file from where I access the above functions:
public static function InsertRecord($inQuery)
{
dbconnection::OpenConnection();
$resultSet = mysql_query($inQuery);
dbconnection::CloseConnection();
return $resultSet;
}
When I remove the line "dbconnection::CloseConnection()", it works fine. I also want to know whether it is a good practice to immediately close the connection as the DB task is finished, or should I keep it open till the use closes the browser?
Try:
class dbconnection {
private static $conn;
public static function OpenConnection() {
require("../Config/dbconfig.php");
self::$conn = mysql_connect(DB_HOST,DB_USER,DB_PASSWORD);
mysql_select_db('MyDB');
}
public static function CloseConnection() {
mysql_close(self::$conn);
}
}
What you're doing is trying to access the member variable $conn but you're doing it incorrectly so you're simply creating a new (local) variable to use. That doesn't matter on open (the reference is simply discarded) but on close you're not dealing with a resource reference anymore.
Secondly, your functions are static but your member variable isn't. These are the two methods you use for accessing member variables:
class A {
private $a;
private static $b;
public static function foo() {
$this->a = 3; // instance member
self::$b = 4; // static member
}
}
Edit: regarding the last function, it works when you remove the call to CloseConnection() because it is no longer trying to access a database connection via the local variable $conn (which will cause an error).
No it isn't good practice to close a database connection immediately. The most common practice in PHP is simply to open a connection at the top of your script and then do nothing more. When the script exits it will close. Some people open connections on demand, meaning it won't try to create one until it needs one. This is an acceptable optimization (from the point of view of not adding unnecessary complexity). Generally the connection will never be explicitly closed. It will be closed implicitly when the script ends.
Long-lived scripts may want to take a different approach just so they don't unnecessarily hold open connections for extended periods.
You may at some point want to use persistent connections instead.
The above method is simple enough and sufficient enough for some pretty large sites. As a general rule, don't try to optimize this stuff and introduce unneeded complexity until you actually have a problem that you need to do something about.

Categories