Best practices when using PHP with Firebird or Interbase - php

The documentation for php-interbase is good - but not complete. In particular, there's no complete examples for working with Firebird. So how would you do it?

Basic guidelines.
Choosing between ibase_connect() vs ibase_pconnect() - the less time connections are active the less possible conflicts and the easier maintenance & backups can be performed. Unless connecting to the database is "expensive" in terms of processing time (you're performing large amounts of real-time reads/writes) use ibase_connect() as needed.
Always use explicit transactions. Always. It's simple - assume every call to ibase_prepare() or ibase_query() requires a transaction handle - never a "raw" connection handle.
Always follow a transaction with either a ibase_commit() or a ibase_rollback() as appropriate.
Basic template for a read operation:
// These would normally come from an include file...
$db_path = '/var/lib/firebird/2.5/data/MyDatabase.fdb';
$db_user = 'SYSDBA';
$db_pass = 'masterkey';
// use php error handling
try {
$dbh = ibase_connect( $db_path, $db_user, $db_pass );
// Failure to connect
if ( !$dbh ) {
throw new Exception( 'Failed to connect to database because: ' . ibase_errmsg(), ibase_errcode() );
}
$th = ibase_trans( $dbh, IBASE_READ+IBASE_COMMITTED+IBASE_REC_NO_VERSION);
if ( !$th ) {
throw new Exception( 'Unable to create new transaction because: ' . ibase_errmsg(), ibase_errcode() );
}
$qs = 'select FIELD1, FIELD2, from SOMETABLE order by FIELD1';
$qh = ibase_query( $th, $qs );
if ( !$qh ) {
throw new Exception( 'Unable to process query because: ' . ibase_errmsg(), ibase_errcode() );
}
$rows = array();
while ( $row = ibase_fetch_object( $qh ) ) {
$rows[] = $row->NODE;
}
// $rows[] now holds results. If there were any.
// Even though nothing was changed the transaction must be
// closed. Commit vs Rollback - question of style, but Commit
// is encouraged. And there shouldn't <gasp>used the S word</gasp>
// be an error for a read-only commit...
if ( !ibase_commit( $th ) ) {
throw new Exception( 'Unable to commit transaction because: ' . ibase_errmsg(), ibase_errcode() );
}
// Good form would dictate error traps for these next two...
// ...but these are the least likely to break...
// and my fingers are getting tired.
// Release PHP memory for the result set, and formally
// close the database connection.
ibase_free_result( $qh );
ibase_close( $dbh );
} catch ( Exception $e ) {
echo "Caught exception: $e\n";
}
// do whatever you need to do with rows[] here...

Related

Is there a way for PHP PDO to detect if a t-sql database is being restored?

I'd like my PHP script (using PDO) to detect whether or not a target database is in the middle of a restore process other than waiting several minutes for a response from a failed connection.
My database connection code eventually returns the message below if a database is being restored, but it happens because the connection fails and it takes several minutes to respond when this happens. Searching on StackOverflow and Google doesn't seem to find anything that fits my need, nor does searching through PHP's documentation.
function getParameterizedPDOConnection($host = false, $overrideOptions = []) {
include(INCLUDE_DIR . "/itrain.config.php");
$host = strtolower($_SERVER["HTTP_HOST"]);
if (count($overrideOptions) > 0) {
$configOptions["host"][$host] = $overrideOptions;
}
$sthUserName = $configOptions["userName"];
$pwd = $configOptions["pwd"];
$addr = $configOptions["host"][$host]["addr"];
$db = $configOptions["host"][$host]["db"];
try {
$pdo = new PDO("sqlsrv:Server=$addr;Database=$db;ConnectionPooling=0", $sthUserName, $pwd, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT));
return($pdo);
} catch (PDOException $e) {
return "Database connection failure: " . $e->getMessage();
}
}
Returns: "42000",927,"[Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Database 'Workforce' cannot be opened. It is in the middle of a restore.

INSERT INTO doesn't write anything in the database

Basically, we are trying to add some values in a database. We are doing it using a GET command to get the value called "valeur" and writing this in the database. However it is not working, the values are not added to the database
<?php
try
{ // connection a la base de donnees
// connection to mySQL
$bdd = new
PDO('mysql:localhost;dbname=test1', 'root', '');
}
catch(Exception $e) //in case of error, display it and stop everything
{
die('Erreur : '.$e->getMessage());
}
if (isset($_GET['temp1'])) // test if the variable exists
{
$_GET['temp1'] = floatval($_GET['temp1']);
echo ('donnee ' .$_GET["temp1"]. ' en cours d\'ecriture</br>');
$bdd->exec('INSERT INTO temp (valeur) VALUES('.$_GET["temp1"].')');
echo ('donnee ' .$_GET['temp1']. ' ecrite!');
}
?>
If we put a value in (in our case) http://localhost/test1/add.php?temp1=(thevalue) then it should be inserted into our table called temp in the column "valeur". Instead, it doesn't write anything.
Edit : We are using PHP version 5.6.19 and MySQL 5.7.11 and WAMPserver
EDIT2: I have finally resolved the problem, though I have no idea how.
Php looks fun
You should assign a variable for the SQL query for debugging target.
And echo to print how is your query string. After that, you paste your $query in SQL tab at Phpmyadmin to know what is your error.
$query = "INSERT INTO temp (valeur) VALUES('.$_GET['temp1'].')";
echo $query;
As you are using PDO it makes sense to utilise some of the strengths of it - primarily in this case prepared statements and bound parameters to make the sql much safer from malicious users.
If you separate the database connection from the remaining code you have a database connection which can be used elsewhere quickly and easily simply by including it at runtime, so the first piece of code below could be the db connection file.
( I see you have solved the problem yourself just before posting this... )
<?php
/*******************
dbo-conn.php
*/
try{
$options=array(
PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL,
PDO::ATTR_PERSISTENT => false,
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
PDO::ATTR_EMULATE_PREPARES => true,
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'utf8mb4\' COLLATE \'utf8mb4_general_ci\', ##sql_mode = STRICT_ALL_TABLES, ##foreign_key_checks = 1'
);
$dbuser='root';
$dbpwd='';
$bdd=new PDO( 'mysql:host=localhost;dbname=test1;port=3306;charset=UTF8', $dbuser, $dbpwd, $options );
}catch( PDOException $e ){
exit( $e->getMessage() );
}
?>
On the page that does the database inserts
<?php
try{
# test that the variable is set and available...
if( !empty( $_GET['temp1'] ) ){
# rudimentary check for number
if( !is_numeric( $_GET['temp1'] ) )throw new Exception( sprintf( 'Supplied parameter "%s" does not appear to be a number', $_GET['temp1'] ) );
$valeur = $_GET['temp1'];
# include the db connection
# the path used here depends where the file `dbo-conn.php` is saved
# - this assumes the same directory
require 'dbo-conn.php';
# generate sql & prepared statement
$sql='insert into `temp` ( `valeur` ) values ( :valeur )';
$stmt = $bdd->prepare( $sql );
# check the prepared statement was created ok before attempting to execute it
if( !$stmt ) throw new Exception( 'Failed to prepare sql "INSERT" query'
# bind the placeholder to the supplied user input
$stmt->bindParam( ':valeur', $valeur, PDO::PARAM_STR );
# commit the query
$result = $stmt->execute();
if( !$result )throw new Exception( 'oops! something went wrong' );
# display a message to the user
printf('donnee %s ecrite!', $valeur );
}
}catch( Exception $e ){
exit( sprintf( 'Erreur: %s', $e->getMessage() ) );
}
?>

Error Checking for PDO Prepared Statements [duplicate]

This question already has answers here:
Why does this PDO statement silently fail?
(2 answers)
Closed 5 years ago.
I'm trying to create proper error handling for queries on a MySQL database using PDO prepared statements. I want the program to exit the moment an error in the prepared statement process is detected. Taking advantage of the fact that each step in the PDO prepared statement process returns False on failure, I threw together this repugnant hack:
global $allFields;
global $db;
global $app;
//dynamically append all relevant fields to query using $allFields global
$selectQuery = 'SELECT ' . implode($allFields, ', ') .
' FROM People WHERE ' . $fieldName . ' = :value';
//prepared statement -- returns boolean false if failure running query; run success check
$success = $selectQueryResult = $db->prepare($selectQuery);
checkSuccess($success);
$success = $selectQueryResult->bindParam(':value', $fieldValue, PDO::PARAM_STR);
checkSuccess($success);
$success = $selectQueryResult->execute();
checkSuccess($success);
with checkSuccess() doing the following:
function checkSuccess($success) {
if ($success == false) {
//TODO: custom error page.
echo "Error connecting to database with this query.";
die();
}
}
Two things. First, this is horribly verbose and stupid. There must be a better way. Obviously I could store the booleans in an array or something to take out a line or 2 of code, but still.
Second, is it even necessary to check these values, or should I just check the result after I perform this line of code:
$result = $selectQueryResult->fetch(PDO::FETCH_ASSOC);
I already have code that does this:
if ($result) { //test if query generated results
// do successful shit
}
else {
echo "404";
$app->response()->status(404); //create 404 response header if no results
As much as I try to break the prepared statement process by inserting weird, mismatched, or lengthy queries, my program always makes it to the $result assignment without returning false on any of the functions where I run checkSuccess(). So maybe I don't need to be checking the above logic at all? Keep in mind that I check for a successful database connection earlier in the program.
I preffer setting the error mode to throwing exceptions like this:
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
right after I connect to the database. So every problem will throw an PDOException
So your code would be:
$selectQuery = '
SELECT
' . implode($allFields, ', ') . '
FROM
People
WHERE
' . $fieldName . ' = :value
';
try
{
$selectQueryResult = $db->prepare($selectQuery);
selectQueryResult->bindParam(':value', $fieldValue);
$selectQueryResult->execute();
}
catch(PDOException $e)
{
handle_sql_errors($selectQuery, $e->getMessage());
}
where the function would be:
function handle_sql_errors($query, $error_message)
{
echo '<pre>';
echo $query;
echo '</pre>';
echo $error_message;
die;
}
In fact I am using a general function that also has something like
$debug = debug_backtrace();
echo 'Found in ' . $debug[0]['file'] . ' on line ' . $debug[0]['line'];
to tell me where was the problem if I am running multiple queries
You have to catch PDOException:
try {
//your code/query
} catch (PDOException $e) {
//Do your error handling here
$message = $e->getMessage();
}
PDOException

Close a php connection

i have a cron Job running following script every 5 min. However it seems that the script doesn't closes the connection once its run . How can I close the connection in this script?
function __construct($config)
{
$this->server = $config['server'];
$this->certificate = $config['certificate'];
$this->passphrase = $config['passphrase'];
// Create a connection to the database.
$this->pdo = new PDO(
'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['dbname'],
$config['db']['username'],
$config['db']['password'],
array());
// If there is an error executing database queries, we want PDO to
// throw an exception.
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// We want the database to handle all strings as UTF-8.
$this->pdo->query('SET NAMES utf8');
}
// This is the main loop for this script. It polls the database for new
// messages, sends them to APNS, sleeps for a few seconds, and repeats this
// forever (or until a fatal error occurs and the script exits).
function start()
{
writeToLog('Connecting to ' . $this->server);
if (!$this->connectToAPNS())
exit;
while (true)
{
// Do at most 20 messages at a time. Note: we send each message in
// a separate packet to APNS. It would be more efficient if we
// combined several messages into one packet, but this script isn't
// smart enough to do that. ;-)
$stmt = $this->pdo->prepare('SELECT * FROM messages WHERE time_sent IS NULL LIMIT 20');
$stmt->execute();
$messages = $stmt->fetchAll(PDO::FETCH_OBJ);
foreach ($messages as $message)
{
if ($this->sendNotification($message->id, $message->token, $message->payload))
{
$stmt = $this->pdo->prepare('UPDATE messages SET time_sent = NOW() WHERE id = ?');
$stmt->execute(array($message->id));
}
else // failed to deliver
{
$this->reconnectToAPNS();
}
}
unset($messages);
sleep(5);
}
}
I may have misread, but apparently you are launching every 5 minutes a script that doesn't exit (infinite loop). So you're stacking the instances, until Earth (or more modestly, your server) eventually explodes.
To answer your question, PHP automatically frees all resources, including DB connexions, when the script execution has ended.
When a script runs for a very long time (like infinite), or there are very specific memory considerations, one can manually frees resources using unset($foo) or $foo = null.[1]
DB connexions can be closed and freed this way too, just with unset($this->pdo).
[1] see also What's better at freeing memory with PHP: unset() or $var = null

The basics of SOAP used with PHP

I know that it's not the main idea of this site to answer such kind of questions but in couple of days I'll have the chance to apply for a junior (or maybe more correctly a probationer) position as a PHP programmer and that's why I decided to post here, hoping it will turn out good.
The company is some kind of big compared to others here, so it's well known what is the exam for people wanting to get in this position - it's either - writing a pagination script or some sort of SOAP service.I have no problem with the pagination, but since now I have never payed too much attention to SOAP and now I need to learn tha basics ot SOAP service when used with PHP.Giving the postion I'm applying for, noone expect to show something brilliant but I still I need basic understanding of SOAP client and server sevices, maybe I won't even bother for now about WSDL since I don't think I have enough time for everything.
So I have a sample code that is most likely what I'll need to write and explain If I'm to write SOAP service :
Client side -
<?php
if (isset($_REQUEST["cname"]) && isset($_REQUEST["cpass"]))
{
$cname = $_REQUEST["cname"];
$md5pass = md5( $_REQUEST["cpass"]);
$client = new SoapClient(null, array(
'location' => "http://localhost/test/BuildInSoapWithWSDL/server.php",
'uri' => "urn://localhost/test/BuildInSoapWithWSDL/",
'trace' => 1 ));
try
{
if ( $client->saveUserNameAndPass($cname, $md5pass))
{echo "Data updated!";}
else
{echo "Error updating data!";}
print "<pre>\n";
print "Request :\n".htmlspecialchars($client->__getLastRequest()) ."\n";
print "Response:\n".htmlspecialchars($client->__getLastResponse())."\n";
print "</pre>";
}
catch (Exception $e)
{
echo 'Exception: ', $e->getMessage(), "\n";
}
}
else
{
echo "Error!";
}
?>
server side -
<?php
$server = new SoapServer(null, array('uri' => 'urn://localhost/test/BuildInSoapWithoutWSDL/'));
$server->addFunction("saveUserNameAndPass");
$server->handle();
function database_connect($host, $account, $password, $dbname)
{
$connect = mysql_connect($host, $account, $password);
$connect = mysql_select_db($dbname, $connect);
return $connect;
}
function saveUserNameAndPass($userName,$passWord)
{
try
{
if (database_connect("localhost", "saveuser", "123456", "savetask") == 1)
{
$userName = mysql_real_escape_string($userName);
$sql = "INSERT INTO accounts (name,passmd5) VALUES ('".$userName."','".$passWord."')";
$result = mysql_query($sql);
mysql_close();
if ($result)
{ return true;}
else
{ return false;}
}
else
{
return false;
}
}
catch (Exception $e)
{
return false;
}
}
?>
Even I have the code I still have poor knowledge of what do what.So I need some explanation ot the basics when writing SOAP service and if it's not acceptable this topci to be discussed here I would appreciate any kind of source where these thing are explained from the point of beginner.
Thanks
SOAP is used just the same as you interact with MySQL database. I can give you real life example, for connections to Atlassian JIRA web application.
At first, you just make connection. You will need an WSDL file, that contains all the stuff, that contains every function that this specific SOAP server allows you to do:
try { $soapObject = new SoapClient('http://jira/rpc/soap/jirasoapservice-v2?wsdl'); }
catch(Exception $ex) { die('SOAP connection failed: '$ex->getMessage()); }
After connection has been made, you just use it. If it is needed, login:
$authToken = $soapObject->login(JIRA_LOGIN, JIRA_PASS);
Then send requests to server:
$jqlquery = "status not in (Closed,Resolved) and assignee = user");
try { $issues = $soapObject->getIssuesFromJqlSearch($authToken, $jqlquery, 20); }
catch(Exception $ex) { die('JIRA query failed: '$ex->getMessage()); }
Work on results:
foreach ($issues as $k => $v) { $users[$v->reporter] = array('fullname'=>$soapObject->getUser($authToken,$v->reporter)->fullname,'name'=>$v->reporter); }
$project = $soapObject->getProjectByKey($authToken,"PROJECT");
Note that getIssuesFromJqlSearch, getUser, getProjectByKey and others, are application-specific commands (in this case, all methods/functions are described in JIRA RPC plugin documentation).
That's it. You don't need to "disconnect", afaik when loading finishes, destructor is called, that closes connection by itself.

Categories