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?
Related
I want to create a simple web page which checks the availability of my several Oracle instances in my lab using PHP 5.4 and OCI 8.
In general it works for all instnaces that are up, but if I have an instance that is down the script exit and the other instances are not checked!??
Let me show you my little code:
<?php
$c1_ORCL11 = oci_connect("system", "mypassword", 'ORCL11');
$c2_ORCL21 = oci_connect("system", "mypassword", 'ORCL21');
$c3_ORCL23 = oci_connect("system", "mypassword", 'ORCL23');
function check_connect ($conn, $sid)
{
if (!$conn) {
$m = oci_error();
echo $m['message'], "\n";
break;
}
else {
print "$sid: Connected to Oracle!<BR>";
}
// Close the Oracle connection
oci_close($conn);
}
check_connect($c1_ORCL11,'ORCL11');
check_connect($c3_ORCL23,'ORCL23');
check_connect($c2_ORCL21,'ORCL22');
?>
Instances ORCL11 and ORCL21 are UP and ORCL23 is DOWN. If I execute the code I got the following output:
ORCL11: Connected to Oracle!
ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
The idea was to get also "ORCL21: Connected to Oracle!", but the code exit if I can not connect to an instance. If I change the order to:
check_connect($c1_ORCL11,'ORCL11');
check_connect($c2_ORCL21,'ORCL21');
check_connect($c3_ORCL23,'ORCL23');
I get the following output:
ORCL11: Connected to Oracle!
ORCL21: Connected to Oracle!
ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
and if I change the order to:
check_connect($c3_ORCL23,'ORCL23');
check_connect($c1_ORCL11,'ORCL11');
check_connect($c2_ORCL21,'ORCL21');
ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
So, If I have a bunch of Instances and the 1st one in the list is DOWN, the other instances are not shown on my web page even if there are UP and running :-(
Any ideas how to fix this?
Thanks in advance for your help!
Regards,
Ralf
After posting the question I saw my mistake ... strange, looked before some hours and didn't find it ... anyway ... it worked fine after removing the "break;" command within the if case. My assumption was to just break out of the if case and continue but it looks like the break exit the whole code at this stage!
Here is the complete code an the result:
<?php
$c1_ORCL11 = oci_connect("system", "<mypasswd>", 'ORCL11');
$c2_ORCL21 = oci_connect("system", "<mypasswd>", 'ORCL21');
$c3_ORCL23 = oci_connect("system", "<mypasswd>", 'ORCL23');
function check_connect ($conn, $sid)
{
if (!$conn) {
$m = oci_error();
echo "$sid: ", $m['message'], "<BR>";
//break;
}
else {
print "$sid: Connected to Oracle!<BR>";
}
// Close the Oracle connection
oci_close($conn);
}
check_connect($c3_ORCL23,'ORCL23');
check_connect($c1_ORCL11,'ORCL11');
check_connect($c2_ORCL21,'ORCL21');
?>
The Output:
ORCL23: ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
ORCL11: Connected to Oracle!
ORCL21: Connected to Oracle!
Regards,
Ralf
I've successfully connected to a remote IBM i DB2 database (AS400) from my local Windows PC via PHP. I'm using the IBM Data Server Client in conjunction with the db2_* functions in PHP. The problem I'm having is that despite my library list being set properly, it is not being used for unqualified table names. Instead it uses the current user name as the library. However, when I qualify the table names everything works like a charm.
I've confirmed that my library list is actually changing when I create the connection by querying QSYS2.LIBRARY_LIST_INFO.
$database = '<database name>';
$user = '<user name>';
$password = '<password';
$port = <port>;
$options['i5_naming'] = DB2_I5_NAMING_ON;
$options['autocommit'] = DB2_AUTOCOMMIT_OFF;
$options['i5_libl'] = 'MYLIB YOURLIB ANYLIB';
$conn = db2_connect($database, $user, $password, $options);
if ($conn) {
echo "Connection succeeded."; //It succeeds
}
else {
echo db2_conn_error()." | ".db2_conn_errormsg()."<br />";
echo "Connection failed.";
}
$sql = "SELECT * FROM QSYS2.LIBRARY_LIST_INFO";
//Works and proves my library list reflects
//what I passed in when creating the connection.
//$sql = "SELECT * FROM LIBRARY_LIST_INFO";
//Generates: "42S02 : [IBM][CLI Driver][AS] SQL0204N "<user name>.LIBRARY_LIST_INFO" is an undefined name. SQLSTATE=42704 SQLCODE=-204"
//where <user name> is the username used to connect to the DB.
//It should be using the library list specified when creating the connection though.
//This holds true for any table from any library including those specified
//when creating the connection (which includes QSYS2).
$stmt = db2_prepare($conn, $sql);
$result = db2_execute($stmt);
if($result){
while($row = db2_fetch_assoc($stmt)){
echo "<pre>";
var_dump($row); //In addition to entries for QSYS, QSYS2, QUSRSYS and QHLPSYS I get entries for MYLIB, YOURLIB and ANYLIB.
echo "</pre>";
}
}else{
echo "failed<br />";
echo db2_stmt_error()." : ".db2_stmt_errormsg()."<br />";
}
Has anyone ever run into this while enabling i5_naming when connecting to a remote DB2 server? I'm not really sure why it wouldn't be using my library list as the PHP manual states "Unqualified files are resolved using the library list for the job." when enabled. http://php.net/manual/en/function.db2-connect.php
I finally solved this after opening a PMR with IBM. All I had to do was apply the latest Fix Pack for DB2 Connect Personal Edition.
Suggested Fix Packs for DB2 Connect:
http://www-01.ibm.com/support/docview.wss?rs=71&uid=swg21321001
Basically the DB2 Connect version I had was released prior to 2013. It was in 2013 IBM added two tier support by adding the i5_naming option. So my DB2 Connect setup was effectively ignoring the option I was passing. So that explains why the other options still went through. On the DB side, since it didn't receive a value for i5_naming - it remained as the default.
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 ....");
I have three update statements to be executed in PHP, i am getting the values of all these as return parameters. How to execute each statement independely and finally show the end user the result that it has been successfully updated.
<?php
public function name($parameter1,$parameter2.... $parametern) {
}
?>
Then how finally we can get the result in my row object.
Ah i think i see, well looks to me from your update statements that you want to update 3 different tables which all depend on 'tycodashboard'.
In that case i advise you use transactions to retain a bit of data integrity, otherwise say if one fails? you'll have lost some data. As a general rule, if you need to do more than 1 update simultaneously use transactions.
Heres a great article on the subject: http://dev.mysql.com/doc/refman/5.0/en/commit.html
Its quite easy to do, just make you sure your tables are using the INNODB, then all you have to do is append START TRANSACTION to the top of your sql script and then COMMIT at the end.
You might be trying to combine too much into a single function, whenever i'm updating multiple tables, it's easier to just handle each one in turn, rather than trying to stuff them all into one return. So try making a function that saves it, returning success or failure, then call it from your main function for each one of your sql scripts passing in the values.
//This is the function that gets called from your page.
public function my_called_function() {
//your sql script (using "" means you can put variables in without having to remove the quotes)
$sql = "UPDATE....SET 'col' = $_POST['myvalue']";
//Run your script and get result
$result = $this->save_my_stuff($sql);
//if not null means success!
if($result) {
echo 'success!'; // your success message
}
else {
echo 'something bad happened'; //your failure message
}
}
//this is the function that does the saving!
private function save_my_stuff($sql_script) {
//Make connection
$conn = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
//Check connection
if(!$conn) {
//connection failed
die('Could not connect: '.mysql_error());
}
//Select your database using your connection object
mysql_select_db(DB_NAME, $conn);
//try and save
try {
//run the query
$result = mysql_query($sql_script, $conn);
//return the result
return mysql_result($result);
}
catch (Exception $e) {
//deal with exception
return null;
}
//close connection
mysql_close();
}
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.