PHP: Close mysql connection when using external connection file - php

So most basic php/mysql examples show something like this (taken from W3 Schools as a laymans example):
<?php
$con=mysqli_connect("example.com","peter","abc123","my_db");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result = mysqli_query($con,"SELECT * FROM Persons");
while($row = mysqli_fetch_array($result))
{
echo $row['FirstName'] . " " . $row['LastName'];
echo "<br />";
}
mysqli_close($con);
?>
When using external connection files, what is the correct way to close the connection (if needed at all).
Eg. We separate the above into a connection.php file which contains
<?php
$con=mysqli_connect("example.com","peter","abc123","my_db");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
?>
And then have a Query.php file that contains:
<?php
require('connection.php');
$result = mysqli_query($con,"SELECT * FROM Persons");
while($row = mysqli_fetch_array($result))
{
echo $row['FirstName'] . " " . $row['LastName'];
echo "<br />";
}
?>
Is it necessary to close the connection. Should there be a mysqli_close($con); at the end of the query.php file, or does it go at the end of the connection.php file and theres some sort of way to link that the query.php file will run before the connection is closed?
And/or is closing the connection even needed? Does it just close automatically after the script is complete?

Open connections (and similar resources) are automatically destroyed at the end of script execution. However, you should still close or free all connections, result sets and statement handles as soon as they are no longer required. This will help return resources to PHP and MySQL faster.
Still, if your PHP script takes lots of time to execute, it's a good idea to close the connection when you don't have to do any request to the database anymore -- at least, if the long calculations are done after the queries.
This is especially true if your application is deployed on a shared hosting : your user account can generally only have a few connections opened at the same time. (That number of simultaneous opened connections can be pretty small on shared hosting ; it's generally bigger on private servers).
The reason we often don't close connections ourselfves is :
we generally don't really know when we have done all our queries --
this is especially true with pages that are made of lots of small
"blocks" ; each one of those is independant from the others, and can
do queries on its own ; so, when can we close the connection ?
web pages are generally quite fast to generate, so we don't really
bother about closing the connection to DB.
I think this may help you to resolve your problem.

It's better to use a class which perhaps extends Mysqli, for ie:
<?php
// Database class
class Database extends \mysqli
{
public function __construct($host, $user, $pass, $db)
{
//create connection
}
public function __destruct()
{
//close connection
//will call this function when class closes or PHP stops
}
}
//using the database
$db = new Database('localhost', 'user', 'pass', 'db');
$db->query("SELECT ....");

Related

"No database selected" when implementing Zebra_pagination with SQL/PHP

Relatively new to PHP and first Stack question, so apologies in advance for any mistakes on my part.
I'm trying to implement Zebra Pagination with my SQL database (using latest MAMP) and getting an error of 'No database selected'. I think the issue lies in how I'm hooking up my connection with Zebra, but not having a ton of luck debugging. The code:
<?php
$servername = "localhost";
$username = "user";
$password = "password";
$dbname = "database";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// how many records should be displayed on a page?
$records_per_page = 10;
// include the pagination class
require 'Zebra_Pagination.php';
// instantiate the pagination object
$pagination = new Zebra_Pagination();
$MySQL = "SELECT SQL_CALC_FOUND_ROWS Id
FROM table
LIMIT
' . (($pagination->get_page() - 1) * $records_per_page) . ', ' . $records_per_page . '
";
$result = $conn->query($MySQL);
// if query could not be executed
if (!($result = #mysql_query($MySQL))) {
// stop execution and display error message
die(mysql_error());
}
// fetch the total number of records in the table
$rows = mysql_fetch_assoc(mysql_query('SELECT FOUND_ROWS() AS rows'));
// pass the total number of records to the pagination class
$pagination->records($rows['rows']);
// records per page
$pagination->records_per_page($records_per_page);
?>
<table class="Id" border="1">
<tr><th>Id</th></tr>
<?php $index = 0?>
<?php while ($row = mysql_fetch_assoc($result)):?>
<tr<?php echo $index++ % 2 ? ' class="even"' : ''?>>
<td><?php echo $row['Id']?></td>
</tr>
<?php endwhile?>
</table>
<?php
// render the pagination links
$pagination->render();
$conn->close();
?>
I'm guessing there's just some dumb beginner's mistake in here. Any/all help would be much appreciated!
I would be sure to test your credentials using the "mysql" command locally or a graphical tool such as Sequel Pro (open source, donationware).
To cite Zebra's source code:
Please note that this is a generic pagination script, meaning that it does not display any records and it does not have any dependencies on database connections or SQL queries, making it very flexible! It is up to the developer to fetch the actual data and display it based on the information returned by this pagination script. The advantage is that it can be used to paginate over records coming from any source like arrays or databases.
So the issue likely does not lie with Zebra. While it's possible it is a permissions issue, either way it's very likely a mis-configuration between your PHP and your MySQL, as referenced here: PHP says "No Database selected" even after using mysqli_select_db()

PHP/MySQL query not working with no error

I have written that seems to not be working, but MySQL does not return any error. It is supposed to get data from database1.table to update database2.table.column
<?php
$dbh1 = mysql_connect('localhost', 'tendesig_zink', 'password') or die("Unable to connect to MySQL");
$dbh2 = mysql_connect('localhost', 'tendesig_zink', 'password', true) or die("Unable to connect to MySQL");
mysql_select_db('tendesig_zink_dev', $dbh1);
mysql_select_db('tendesig_zink_production', $dbh2);
$query = " UPDATE
tendesig_zink_dev.euid0_hikashop_product,
tendeig_zink_production.euid0_hikashop_product
SET
tendesig_zink_dev.euid0_hikashop_product.product_quantity = tendesig_zink_production.euid0_hikashop_product.product_quantity
WHERE
tendesig_zink_dev.euid0_hikashop_product.product_id = tendesig_zink_production.euid0_hikashop_product.product_id";
if (mysql_query($query, $dbh1 ))
{
echo "Record inserted";
}
else
{
echo "Error inserting record: " . mysql_error();
}
?>
The manual page for mysql_error() mentions this about the optional parameter you're omitting:
link_identifier
The MySQL connection. If the link identifier is not
specified, the last link opened by mysql_connect() is assumed. If no
such link is found, it will try to create one as if mysql_connect()
was called with no arguments. If no connection is found or
established, an E_WARNING level error is generated.
So it's reading errors from $dbh2, which is the last connection you've opened. However, you never run any query on $dbh2:
mysql_query($query, $dbh1 )
Thus you get no errors because you are reading errors from the wrong connection.
The solution is to be explicit:
mysql_error($dbh1)
As about what you're trying to accomplish, while you can open as many connections as you want, those connections won't merge as you seem to expect: they're independent sessions to all effects.
All your tables are on the same server and you connect with the same users, there's absolutely no need to even use two connections anyway.
You can't just issue a cross-database update statement from PHP like that!
You will need to execute a query to read data from the source db (execute that on the source database connection: $dbh2 in your example) and then separately write and execute a query to insert/update the target database (execute the insert/update query on the target database connection: $dbh1 in your example).
Essentially, you'll end up with a loop that reads data from the source, and executes the update query on each iteration, for each value you're reading from the source.
I appreciate everyone's help/banter, here is what finally worked for me.
<?php
$dba = mysqli_connect('localhost', 'tendesig_zink', 'pswd', 'tendesig_zink_production') or die("Unable to connect to MySQL");
$query = " UPDATE
tendesig_zink_dev.euid0_hikashop_product, tendesig_zink_production.euid0_hikashop_product
SET
tendesig_zink_dev.euid0_hikashop_product.product_quantity = tendesig_zink_production.euid0_hikashop_product.product_quantity
WHERE
tendesig_zink_dev.euid0_hikashop_product.product_id = tendesig_zink_production.euid0_hikashop_product.product_id";
if (mysqli_query($dba, $query))
{
echo "Records inserted";
}
else
{
echo "Error inserting records: " . mysqli_error($dba);
}
?>

PHP mysql_connection close

I am new to PHP but I am strong in classic ASP, so I am based on classic ASP to learn and pickup PHP.
Since I have only one database to connect, so I created a function to connect to it and return record set, then I want to close the record set after I finished with it. (I am following my classic ASP practice)
I made a function to connect to ODBC then the function will return the RS as follow:
function connection_open($strSQL)
{
$conn=odbc_connect('dbreadonly','dbreadonly','readonly');
if (!$conn)
{exit("Connection Failed: " . $conn);}
$myRS=odbc_exec($conn,$strSQL);
return $myRS;
}
$sql="SELECT * FROM TblUsers";
$rs=connection_open($sql);
if (!$rs)
{exit("Error in SQL");}
while (odbc_fetch_row($rs))
{
$username=odbc_result($rs,"UserName");
echo "<td>$username</td></tr>";
}
Now, how do I close the connection if outside the function?

Using Session code instead of PHP SELECT WHERE function

Since my question may be unclear:
in short I am wanting to make the following code shorter and/or faster
I have login system that starts a session and runs until you logout
I also have a SELECT WHERE script that counts how many invoices have not been paid that is working just fine but is long, ugly, and bulky like so:
<?php
$con=mysqli_connect("REMOVED FOR SECURITY");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result = mysqli_query($con,"SELECT COUNT(*) FROM mypanda_invoices
WHERE is_paid='0'");
while($row = mysqli_fetch_array($result))
{
echo "<span class='badge badge-important'>" . $row['COUNT(*)'] . "</span>";
}
?>
Right now to get the users username I have: <?php session_start(); echo $_SESSION['username']; ?> is there someway I could do this same type of thing with the code I have above? Just to make it shorter and take advantage of the session??? Thank you in advance.
As long as the session has started, you can put the invoice count in the session as well.
If you want the code cleaner, I would recommend checking for a result set and then using fetch_object()->inv_count (or, in PHP 5.4, you could use fetch_array(MYSQLI_NUM)[0] I guess).
If you have an error with a vital part of your system -- the database connection for example, you should handle it gracefully (my die below isn't graceful, but it gets the job done) instead of just echoing and continuing on, which will result in a fatal error later on.
Also, using objects will make things a bit cleaner as well.
<?php
$con = new mysqli("REMOVED FOR SECURITY");
// Check connection
if(mysqli_connect_errno()) die("Failed to connect to MySQL: " . mysqli_connect_error());
$result = $con->query("SELECT COUNT(*) AS inv_count FROM mypanda_invoices
WHERE is_paid='0'");
if($result && $result->num_rows) $_SESSION['inv_count'] = $con->fetch_object()->inv_count;
else $_SESSION['inv_count'] = 0;
echo "<span class='badge badge-important'>" . $_SESSION['inv_count'] . "</span>";

PHP echo query result in Class?

I have a question about PHP Class. I am trying to get the result from Mysql via PHP. I would like to know if the best practice is to display the result inside the Class or store the result and handle it in html.
For example, display result inside the Class
class Schedule {
public $currentWeek;
function teamQuery($currentWeek){
$this->currentWeek=$currentWeek;
}
function getSchedule(){
$connection = mysql_connect(DB_SERVER,DB_USER,DB_PASS);
if (!$connection) {
die("Database connection failed: " . mysql_error());
}
$db_select = mysql_select_db(DB_NAME,$connection);
if (!$db_select) {
die("Database selection failed: " . mysql_error());
}
$scheduleQuery=mysql_query("SELECT guest, home, time, winner, pickEnable FROM $this->currentWeek ORDER BY time", $connection);
if (!$scheduleQuery){
die("database has errors: ".mysql_error());
}
while($row=mysql_fetch_array($scheduleQuery, MYSQL_NUMS)){
//display the result..ex: echo $row['winner'];
}
mysql_close($scheduleQuery);
//no returns
}
}
Or return the query result as a variable and handle in php
class Schedule {
public $currentWeek;
function teamQuery($currentWeek){
$this->currentWeek=$currentWeek;
}
function getSchedule(){
$connection = mysql_connect(DB_SERVER,DB_USER,DB_PASS);
if (!$connection) {
die("Database connection failed: " . mysql_error());
}
$db_select = mysql_select_db(DB_NAME,$connection);
if (!$db_select) {
die("Database selection failed: " . mysql_error());
}
$scheduleQuery=mysql_query("SELECT guest, home, time, winner, pickEnable FROM $this->currentWeek ORDER BY time", $connection);
if (!$scheduleQuery){
die("database has errors: ".mysql_error());
// create an array }
$ret = array();
while($row=mysql_fetch_array($scheduleQuery, MYSQL_NUMS)){
$ret[]=$row;
}
mysql_close($scheduleQuery);
return $ret; // and handle the return value in php
}
}
Two things here:
I found that returned variable in php is a little bit complex to play with since it is two dimension array. I am not sure what the best practice is and would like to ask you experts opinions.
Every time I create a new method, I have to recreate the $connection variable: see below
$connection = mysql_connect(DB_SERVER,DB_USER,DB_PASS);
if (!$connection) {
die("Database connection failed: " . mysql_error());
}
$db_select = mysql_select_db(DB_NAME,$connection);
if (!$db_select) {
die("Database selection failed: " . mysql_error());
}
It seems like redundant to me. Can I only do it once instead of calling it anytime I need a query? I am new to php class. hope you guys can help me. thanks.
I treat classes like these as 'accessors' so they purely query the database and return the result. That way any PHP code which calls it can do whatever it likes with it. this may be displaying or it may be a check or it may be an update. This is good design as it separates the datastore from the logic from the display and means your code will be more flexible. But yes, it is a little more complex.
In regards to re-creating the connection each time. This may or may not be necessary. Depending on your setup you may be able to create a connection pool. To make it easier for you for now, you can abstract the creation of a connection to its own method. This way you only need to call this method at the start to get a connection handle. This saves you from having many copies of the same code all over the place.
If you are new to PHP classes I suggest doing a bit of research on object oriented design. This will give you an idea on why it would be beneficial to abstract some functions, and also why you would want to return the results instead of displaying them.
Its probably a bad idea to echo the result int he class nstead you should return the result or result set for echoing else where.
May the connection a mebmer of the class like:
protected $_connection = null;
Then in your constructor you can assign the database connection. Though normally your db connection would be wrapped by yet another class.
Additionally if i were you i would not use the mysql functions. Instead use the Mysqli or PDO_Mysql drivers. They encapsulate all this functionality in an object orientend manner by default. You can then extend those classes with your custom functionality instead of working from scratch.

Categories