My question is I am using the variable $db in my general script code and within one of my functions. It's purpose is to be the variable that is used for MySQL connections. I have a need inside a function to write some data to the database. In my script I cannot assume that an existing db connection will be open so I open a new one and close it before the function exits. Ever since doing this I am getting an error after the script runs saying the MySQL reference is bad / doesn't exist.
The only thing I can pin it to is in my core code I use the variable $db as the variable name for database connection. I also use the same variable in the function. I did not imagine this would be a problem because I do not use global in front of $db in the function. This should mean the $db I reference in my function is in the functions private scope but it seems to be closing the public $db's connection.
Any thoughts?
Fragments of my code are:
database.php
db_connect()
{
// open mysql db connection and return it;
}
db_close( &$db )
{
// close the passed by reference db connection
}
api.php
api_verify( $keyid, $userid, $key )
{
// open a new db connection
$db = db_connect();
// check for errors. if any errors are found note them in the db
// close the db
db_close($db);
}
main.php
include api.php;
include database.php;
// open a connection to the db
$db = db_connect();
// pull a list of things to process from the db and move through them one at a time
// call api_verify() on each key before working through it's data.
db_close($db)
To manage DB connections, you can create a class rather than a pair of functions. If where you say "MySQL reference", the exact error refers to a "MySQL resource", then you are using the outdated mysql extension and should switch to a more modern extension, such as PDO.
class DBConnection {
protected static $_connections = array(),
static connect($dsn) {
if (!isset(self::$_connections[$dsn])) {
$credentials = self::getCredentials();
/* Create connection. For example: */
try {
self::$_connections[$dsn][0] = new PDO($dsn, $credentials['username'], $credentials['password']);
} catch (PDOException $exc) {
// erase the frame w/ password from call trace to prevent leak.
throw new PDOException($exc->getMessage(), $exc->getCode());
}
/* End create connection example */
self::$_connections[$dsn][0]->dsn = $dsn;
}
++self::$_connections[$dsn]['count'];
return self::$_connections[$dsn][0];
}
static close($db) {
if (isset(self::$_connections[$db->dsn])) {
if (--(self::$_connections[$db->dsn]['count']) < 1) {
unset(self::$_connections[$db->dsn]);
}
}
}
static getCredentials() {
/* credentials can be stored in configuration file or script, in this method, or some other approach of your own devising */
}
}
Note that this isn't exactly OOP (it is, but only in a technical sense). The above doesn't lend itself well to unit testing. If you want a more OO approach (which will be more amenable to unit testing), extend or wrap PDO. Using dependency injection can also help with the coupling issues of the above.
I assume you are opening a connection to the same database with the same username/password at each of the places you call db_connect. When doing so,unless your db_connect explicitly specifies, that you are creating a new link, it will return an already opened link.If that link is then closed using db_close(), it will also close the other connection, since the link is the same. If you are using mysql_connect to connect to the database, it takes an argument called new link
new_link
If a second call is made to mysql_connect() with the same arguments, no new link will be established, but instead, the link identifier of the already opened link will be returned. The new_link parameter modifies this behavior and makes mysql_connect() always open a new link, even if mysql_connect() was called before with the same parameters. In SQL safe mode, this parameter is ignored.
Refer to http://php.net/manual/en/function.mysql-connect.php
I'm not sure if this is the issue you are facing. Hope it helps.
I would assume what is happening is the connect cancels out because there already is a connection, and then the close ends the current connection.
I would recommend either A) start a connection at the beginning of the file, and just know it's always there (what I do); or B) check the to see if the $db variable is set, if not then create the connection, and always end the connection at the end of the file.
Related
I have a quick question to you guys, i have created the CFG file which stores my database connection detail in two dimensional array. I then connect it to my PHP class file and make it launch the arrays stated in CFG file. As you can see below in my code:
cfg.php
<?php
$cfg['db']['host'] = 'localhost';
$cfg['db']['user'] = 'root'; //your user name
$cfg['db']['pass'] = ''; //your password
$cfg['db']['db'] = 'db3'; //your database
?>
and my class file :
<?php
require_once(dirname(__FILE__) . 'cfg.php');
class Database {
private $dbConn; //stores the database connection
public function __construct($dbConn)
{
global $cfg;
mysql_connect(DB_HOST,DB_USER,DB_PASSWORD) or die('Could not connect to MySQL server.');
mysql_select_db(DB_DATABASE)or die('Unable to select database: ');
}
}
What i want to ask you is: is this right way of doing this? also what do I need to add in my index to see that it is connected. and the output of the database content. Thank you in advance for taking time and reading my problem. Cheerio.
Edit :
<?php
require_once(dirname(__FILE__) . 'cfg.php');
class Database {
private $dbConn; //stores the database connection
public function __construct($dbConn)
{
global $cfg;
mysqli_connect($cfg['db']['host'], $cfg['db']['user'], $cfg['db']['pass'])
or die('Could not connect to MySQL server.');
mysqli_select_db($dbConn, $cfg['db']['db'])
or die('Unable to select database: ');
}
}
Does this looks better now? If yes. How do i connect it with the index.php file where my forms will be stored. say to output the message of (connected to database). Thank you.
EDIT: changed to mysqli and now when selecting the database it states that i am missing the database name. Not sure where to put that and how to alter it. Thank you.
EDIT: I am on my way to create functions for 'Select' 'Insert' and 'Delete' . If any of you can point me do a great source of information which will help me in my research it will be most appreciated.
You are using constants instead of the actual values from your config in your mysql_connect() function, so that wouldn't work. You would need to do it this way:
mysql_connect($cfg['db']['host'], $cfg['db']['user'], $cfg['db']['pass'])
Aside from that and OO paradigms, it would probably be better if you used PHP's mysqli (as stated here) or PDO, as PHP's mysql_ is pretty outdated.
No you are not doing it correctly. By using this line
require_once(dirname(__FILE__) . 'cfg.php');
in your class file you have introduced a somewhat tight coupling to the config file and you have made it hard to swap it out for other credentials. I.e. you will have to change the file with the Database class in it to change the credentials. So start by dropping that include there.
Another thing you do is using the global keyword which is as far from OOP as you could possibly get. Inject the information the class needs instead.
Also you are using the ancient, deprecated and soon to be removed mysql_* API. You are also calling the execution of your script of something fails (or die()) which makes it impossible to integrate your code in a project and also makes it impossible to correctly handle errors (i.e. custom error page).
When upgrading to a better database API (e.g. PDO) you even don't have the need anymore to use a database class at all.
The above would simply look something like the following:
bootstrap.php
try {
$dbConnection = new \PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass');
$dbConnection->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
$dbConnection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
} catch (\PDOException $e) {
// nicely handle error here
}
Alternatively you could implement lazy loading for the database connection depending on your requirements.
As you can see now there is no need for an external config file (you can just change the credentials here in the bootstrap file) and there is no need for a database class.
I am used to mysql database access using the procedural mysql method. I am a beginner - intermediate programmer.
I am trying to learn the PDO api, however all resources which discuss using PDO show the connection string, username and password.
e.g.
<?php
try {
$db_conn = new PDO('mysql:host=localhost;dbname=databaseName','username', 'password');
}
catch (PDOException $e) {
echo 'Could not connect to database';
}
$sql = 'SELECT * FROM Products';
$stmt = $db_conn->prepare($sql);
...
...
...
?>
What I want, and think would be better programming is to put my PDO connection into a new file. then where I want to run an SQL query, I require_once('PDO.php') or similar.
The problem I have with this is as follows:
How do I close the connection? Simply $db_conn = null; ??
Should I close the connection after each query is run, then re-open the connection?
Should I close the connection or is it automatically destroyed when the user closes the browser?
I am working from a book called PHP Master: Writing Cutting Edge Code. http://www.sitepoint.com/books/phppro1/ and this has completely omitted any reference to closing the connection / destroying the object after it has been used.
Furthermore, I have looked at online tutorials, and they all connect to the database using PDO inline as opposed to having a separate database connector. This I am not happy with for many reasons:
I have to type username & password to connect every time.
If I get a developer to take a look at code / write some code, they will all have access to the database.
If I change the DB username & Password, then each file which connects to the database will need to be updated.
Could anybody recommend a better resource? Could anybody advise on what is the best practice way to do this?
Many thanks
Your question about how to store the database name, username and password have nothing to do with the capabilities of PDO. This is an implementation choice. The way you use to work with procedural functions can also be applied to PDO, the difference is that with PDO you work with objects instead.
So for simplicity, store the PDO creation of an object, either in a function or class, in which you can create the PDO instance anytime, e.g.
function createPDO($cfg) {
try {
return new PDO("mysql:host=".$cfg['host'].",port:".($cfg['port']).";dbname=".($cfg['name']).";",$cfg['username'], $cfg['password']);
} catch(PDOException $e) {
// handle exceptions accordingly
}
}
You can centralise these in whatever PHP file you like to include, just like you were used with the procedural functions.
You have two choices, either put all the relevant database information inside the createPDO, or use something like a config ($cfg) variable to store all this information.
$config = array();
$config['db'] = array(
'host' => 'localhost',
'name' => 'databse',
'username' => 'userx',
'password' => 'passy'
/* .. etc */
)
Using the createPDO function would be as followed
$db_conn = createPDO($config['db']);
For connections closing, each connection made to the database automatically disconnects after PHP exits its execution. You can however, close the connection if you wish, by setting the variable of the PDO object you assigned it to, in this example (and in yours) $db_conn to null
$db_conn = null; // connection closed.
The PDO has a manual http://php.net/manual/en/book.pdo.php here, which is a good start getting to know PDO a bit better.
You do not close the connection after a query, you simply leave it open for the next query. When PHP exists and your page is shown, the connection will be closed automatic.
It is a good idea to put the db stuff in a separate file and include that.
Even better, put all your db stuff in a class in use that.
Have a look at the pdo php page. Although not the best examples, they should get you started.
I have a webpage with some mysql querys,
I must start new db connection and db close after every query or its more efficiently start an only one db connection at the top of the code and close at the bottom of the script?
Thanks!
Never create a new connection for every query; it's very wasteful and will overburden your MySQL server.
Creating one connection at the top of your script is enough - all subsequent queries will use that connection until the end of the page. You can even use that connection in other scripts that are include()ed into the script with your mysql_connect() call in it.
I prefer to create some sort of class called Database of which upon creation will create a database connection using mysqli (OOP version of mysql).
This way i do not have to worry about that and i have a static class that has access to the database.
class MyAPI {
private static $database = false;
public static function GetDatabase() {
if (MyAPI::$database === false) {
MyAPI::$database = new Database(credentials can go here)
}
return MyAPI::$database;
}
}
Now your system with the includsion of your API and your database can access the database and its initialization code does not have to be peppered around your files depending on what part of the program is running and your database/connection will not be created if it is not needed (only until it is called).
Just for fun i also like to have a function in my Database class that will perform a query and return its results, this way i do not have to have the SAME while loop over and over again throughout my code depending on where i make these calls.
I also forgot to answer your question. No multiple connections! its baaaad.
Only create one connection. You don't even have to close it manually.
multiple connexion is better for security and tracking.
if you're going though a firewall between front and back there will be a timeout defined so a single connection will be a problem.
but if your web server is on the same host as mysql, a single connection will be more efficient.
HI everyone, I was just wondering what the best way to make multiple queries against tables in a mysql databases is. Should I be making a new mysqli object for every different .php page ($mysqli = new mysqli("localhost", "root", "root", "db");)?
Or is there a way to reuse this one time over all php files in my website? Any suggestions would be pretty cool
My vote would be to take an OOP approach. I would have one script that has a DB conn class in it and a method in that class to check if a connection exists and if it does returns the connection object. You could have that db class script referenced [ include_once(); ] on the pages that need to access the database. Then it would be a matter of instantiating the db object, firing the "if-exists" method and if it returns true then just utilize the existing connection within the object.
You could also take a look at utilizing persitent connections to the DB
Persistent connections
However honestly you will be better off in the long run and scalability of your application to handle the db connection management yourself rather then leaving a connection constantly open.
Here is an example of how I would structure that class:
As a note, made by #alex, the mysql_error() should not be echoed to the page in an environment where the display_errors() is set to display all warnings. (e.g error_reporting(E_WARNING);)
class dbconn {
protected $database;
function __construct(){
$this->connect();
}
protected function connect() {
$this->database = mysql_connect('host', 'user', 'pass') or die("<p>Error connecting to the database<br /><strong>" . mysql_error() ."</strong></p>" );
mysql_select_db('databasename') or die("<p>Error selecting the database<br />" . mysql_error() . "</strong></p>");
}
function __destruct(){
mysql_close($this->database);
}
function db(){
if (!isset($this->database)) {
$this->connect();
}
return $this->database;
}
}
You need to create the connection for each page, as each PHP script's lifetime is that of the request.
However, you can place the connection code in one file and then include it from all pages.
You could create a connect.php that validates it's being included by your application, and then creates a DB connection.
You could then include that file at the beginning of your application's init, or the beginning of any independent script that needs a connection =)
Depends on structure of website. If you have:
<a herf='login.php'>login</a>
<a herf='register.php'>register</a>
<a herf='about.php'>about</a>
..., then you'll have to connect in every PHP file, i.e., in login.php, in register.php and in about.php. To make it easier, I would either create config.php file which holds user/pass, or even do like Shad said.
You might also have index.php that contains something like this:
if ( !isset($_GET['module']) ) {
$_GET['module'] = 'about';
}
switch ( $_GET['module'] ) {
default:
case 'about':
include 'about.php';
break;
case 'login':
include 'login.php';
break;
case 'register':
include 'register.php';
break;
}
And HTML code:
<a herf='?module=login'>login</a>
<a herf='?module=register'>register</a>
<a herf='?module=about'>about</a>
In this case you can connect in index.php and then pass the connection to all other involved files.
The 2nd way seems to be more common to me, i.e., it feels more intuitive, more handy and that's what I always do.
I believe that in some cases it might be worthy (performance-wise) to use persistent connections and reserve/release connection when needed (either for transaction or even for single query). For example, simple system that I'm now working with takes 70ms-100ms to generate, and it takes only 40ms-50ms to do SQL queries. If using "single connection" approach, it means that connection is wasted for about 50% of time, while "reserve/release connection when needed" with persistent connections would not have such issue.
One more thing - I would advise you to create some wrapper, i.e., some DBConnection class that connects to DB in constructor and has methods like select() (returns array of data), selectValue() (returns single value, e.g., $db->selectValue('select count(*) from user') would return (int)$numberOfUsers), some exec() for inserts and updates etc.
This question already has answers here:
Fully Understanding PDO ATTR_PERSISTENT
(4 answers)
Closed 6 years ago.
I have the following code and freshed this webpage in Firefox for 5 times, then the MySQL showed me 5 connections. According to the PDO Manual,
Persistent connections are not closed
at the end of the script, but are
cached and re-used when another script
requests a connection using the same
credentials. The persistent connection
cache allows you to avoid the overhead
of establishing a new connection every
time a script needs to talk to a
database, resulting in a faster web
application.
I have used the same credentials, but the number of MYSQL connection keep increasing. Even trying to close connection with $db = null could not close the connections.
What's wrong of my code?
<?php
try {
$dbh = new PDO('mysql:host=127.0.0.1;dbname=lingtong', 'root', 'xxxxxx', array(PDO::ATTR_PERSISTENT => true));
foreach ($dbh->query('SELECT * from agent') as $row)
print_r($row);
$dbh = null;
} catch (PDOException $e) {
print "Error! : " . $e->getMessage() . "<br/>";
die();
}
This question is very old but it will be okay if I contribute. I think you need to implement a singleton class for handling database connections I will write a sample class below ..
<?php
class DB{
//set the connection property to private to prevent direct access
private static $conn;
//now since we dont want to reinstiate the class anytime we need it, lets also set the constructor to private
private function __construct(){}
//now lets create our method for connecting to the database
public static function connect(){
//now lets check if a connection exists already in our $conn property, then we should return it instead of recreating a new connection
if(!empty(self::$conn)){
return self::$conn;
}//end if
//upon reaching here means the $conn property is empty so lets create a new connection
try {
$dbh = new PDO('mysql:host=127.0.0.1;dbname=lingtong', 'root', 'xxxxxx', array(PDO::ATTR_PERSISTENT => true));
//lets now assign the database connection to our $conn property
self::$conn = $dbh;
//return the connection
return $dbh;
} catch (PDOException $e) {
print "Error! : " . $e->getMessage() . "<br/>";
die();
}
}//end method
}//end class
?>
Our singleton class can make only one connection and reuse it,let see how we can use our class
<?php
$dbh = DB::connect();
foreach ($dbh->query('SELECT * from agent') as $row){
print_r($row);
}
?>
It seems you need to close the cursor and release (assign null) to the last pdo statement object as well to close the connection.
Also, what's important to understand about persistent connections is that they persist, but you are not guaranteed that you will neither:
Be given back your last connection handler in further script executions
Nor be reusing a previous connection, if it's still "busy". Busy may mean in a script, timing out etc... Connections instanciation may go on and on... See Fully Understanding PDO ATTR_PERSISTENT
From what I know from persistent connection you probably doesn't need it:
you are on localhost so the connection is very fast and you wont save a lot from caching of your connection
because of the underlying principal of Apache you have many thread that answer the client request and because of these multi-threading the connection is persistent in a single thread, not shared on all of them so you will see your number of connection go up in mysql until it's reach the ThreadLimit of apache
there is a few risk that persistent connection cause problem to your app in the kind of dbLock or tableLock
Now you might wanna do a bit more research about persistent connections if you still think that you really need it