How to use PDO to fetch data - php

Below are details:
1. PDO connect class which have the function to connect with DB. Say PDO_connect class.
2. Logic class file say MyLogic file, MyLogic file include PDO_connect and another class in which functions are written say MyFunction Class.
Problem :
I am not able execute select query and fetch object using below query.
MyFunction Class have function :
function gCD($query_type,$connection_obj,$u_id,$c_id)
{
if($query_type == 'SELECT')
{
$prepare_sql = $connection_obj->prepare("SELECT c_n from cs where u_id=:u_id and c_id=:c_id");
$query_select_clients = $prepare_sql->execute(array(':u_id'=>$u_id,':c_id'=>$c_id));
echo "\n".$prepare_sql->rowCount();
exit; //This is also not working.
$g_c_obj = $prepare_sql->fetch(PDO::FETCH_OBJ);
var_dump($g_c_obj);
}
}
All arguments are passed from MyLogic File, connection and other details.
If I do this debugging it returns true:
var_dump($prepare_sql->execute(array(':u_id'=>$u_id,':c_id'=>$c_id)))
But neither rowCount() nor fetch() are giving any output. Your help is highly valuable.

This information was too long for a comment so I am typing this as an answer to help debug your case.
Test each case as you go through using PDO functionality. Each functionality like prepare, execute and fetch have a return value. Capture the return value, analyze it and act based on the return value. Substitute your information in appropriate places and see where your execution path stops.
<?php
$db = new PDO('mysql:host=localhost;dbname=xyz', 'user', 'pass');
gCD('SELECT', $db, 2, 2);
function gCD($query_type,$connection_obj,$u_id,$c_id)
{
if($query_type == 'SELECT')
{
try
{
$prepare_sql = $connection_obj->prepare("SELECT c_n from cs where u_id=:u_id and c_id=:c_id");
if ($prepare_sql === false)
{
echo "PDO prepare failed\n";
return false;
}
$query_select_clients = $prepare_sql->execute(array(':u_id'=>$u_id,':c_id'=>$c_id));
if ($query_select_clients === false)
{
echo "PDO execute failed\n";
return false;
}
echo "\n".$prepare_sql->rowCount();
$g_c_obj = $prepare_sql->fetch(PDO::FETCH_OBJ);
if ($g_c_obj === false)
{
echo "PDO fetch failed\n";
return false;
}
var_dump($g_c_obj);
return true;
}
catch (Exception $e)
{
echo 'Exception: ', $e->getMessage(), "\n";
}
}
else
{
echo 'Not a select statement', "\n";
}
return false;
}
?>

Related

PDO PHP Update Script not working

I've searched on stackoverflow and other sources but I cant seem to find the issue that is preventing my PHP script from working.
Look at the echo_sql. It produces a healthy update statement which when run updates the database with no problem. Here is a sample:
update waste set waste_name=1 where id =82;
However, when the script is run, it does not apply changes to the database. Here is the script:
if ($_SERVER['REQUEST_METHOD'] == "POST") {
try {
$waste_id = $_POST['waste_id'];
$sql = new db;
$sql->beginTransaction();
$waste_name = $_POST['waste_name'];
$sql->query("update waste set waste_name=:waste_name where id =:waste_id;");
$echo_sql = "update waste set waste_name=$waste_name where id =$waste_id;";
echo $echo_sql;
$sql->bind(':waste_name', $waste_name);
$sql->execute();
$sql->endTransaction();
} catch (Exception $e) {
$sql->rollBack();
echo "Failed: " . $e->getMessage();
}
}
Additional details:
errorCode() = 00000
DB Class:
class db
{
private $stmt;
private $dbc;
public function __construct()
{
$u = "root";
$p = "";
try {
$this->dbc = new PDO('mysql:host=127.0.0.1;dbname=wimsdb', $u, $p);
$this->dbc->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
$e->getMessage();
}
}
public function bind($param, $value, $type = NULL)
{
$this->stmt->bindParam($param, $value, $type);
}
public function beginTransaction()
{
return $this->dbc->beginTransaction();
}
public function rollBack()
{
return $this->dbc->rollBack();
}
public function endTransaction()
{
return $this->dbc->commit();
}
public function cancelTransaction()
{
return $this->dbc->rollBack();
}
public function execute()
{
try {
return $this->stmt->execute();
} catch (PDOException $e) {
return $e->errorInfo;
}
}
public function errorCode()
{
return $this->stmt->errorCode();
}
public function query($query)
{
$this->stmt = $this->dbc->prepare($query);
}
}
Please offer your suggestions on how this could be resolved.
You need to bind the :waste_id too:
$waste_id = $_POST['waste_id'];
$sql = new db;
$sql->beginTransaction();
$waste_name = $_POST['waste_name'];
$sql->query("update waste set waste_name=:waste_name where id =:waste_id;");
$sql->bind(':waste_name', $waste_name);
$sql->bind(':waste_id', $waste_id);
Any time you have an issue like this your error checking should return a meaningful message letting you know where the error is and likely what the error is. You should be able to check your error logs for details and/or output them to your screen during testing.
Add waste_id. To avoid missing parameters, I like putting the parameteers into the execute method. The bind method could be defined anywhere in the code so I had to look through your code and make sure waste_id binding wasn't defined somewhere else. When it's in the execute method, you can quickly see all parameters being defined there...it's also a tad more concise...but both have their uses.
if ($_SERVER['REQUEST_METHOD'] == "POST") {
try {
$waste_id = $_POST['waste_id'];
$sql = new db;
$sql->beginTransaction();
$waste_name = $_POST['waste_name'];
$sql->query("update waste set waste_name=:waste_name where id =:waste_id;");
$echo_sql = "update waste set waste_name=$waste_name where id =$waste_id;";
echo $echo_sql;
//just because I like this syntax for being concise and clear :)
$sql->execute(array(
'waste_id' => $waste_id,
'waste_name' => $waste_name
));
$sql->endTransaction();
} catch (Exception $e) {
$sql->rollBack();
echo "Failed: " . $e->getMessage();
}

How to return errors from PHP method?

I have a save method in my User class.
If the save method encounters validation errors it returns an array of errors that I display to the user. However this means in my code I have to write:
if (!$user->save()) {
//display success to user
}
Surely my save method should return true on success. But how do I handle errors in that case?
Use try ... catch syntax.
For example:
try {
$user->save();
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
http://php.net/manual/en/language.exceptions.php
I would throw an exception in the event that save() runs into any problems.
If you want to provide an array of validation errors, your could subclass Exception and provide a mechanism for storing the validation errors.
A custom Exception subclass will also help you differentiate between exceptions your code throws explicitly (which you'd like to catch) and exceptions that you didn't expect (which should be fatal).
Here's the subclass:
class UserException extends Exception
{
private $userMessages;
public function __construct($message = "", $code = 0, Exception $previous = null, array $userMessages = null)
{
parent::__construct($message, $code, $previous);
if ($userMessages === null) {
$this->userMessages = array();
} else {
$this->userMessages = $userMessages;
}
}
public function getUserMessages()
{
return $this->userMessages;
}
}
Here's a silly version of a User class that always throws an Exception on save().
class User
{
public function save()
{
$userMessages = array(
'Your password is wrong',
'Your username is silly',
'Your favorite color is ugly'
);
throw new UserException('User Errors', 0 , null, $userMessages);
}
}
To use it:
$user = new User();
try {
$user->save();
} catch (UserException $e) {
foreach ($e->getUserMessages() as $message) {
print $message . "\n";
}
}
You could also accomplish something like this by populating the Exception's $message with, say a semi-colon-delimited list of messages. You could even build a list of constants for error types, then combine them as a bitmask and use that for the Exception's $code. The advantage of these options is you would be using the built in members and not adding anything extra.
More on exceptions:
http://php.net/manual/en/language.exceptions.php
A (bad?) habit I picked up after playing a good bit with erlang is to return tuple values (as a php array).
function my_func() {
$success = true;
$errors = array();
if ( something_fails() ) {
$success = false;
$errors[] = 'something failed..';
}
return array( $success, $errors );
}
list($success, $errors) = my_func();
if ( ! $success ) {
do_somthing_with( $errors );
}
In my experience, this has been really handy when the wild modify legacy code tickets appear and you don't really dare modify anything but could more easily add more legacy to it.
Cheers -
Return either true, or the error array.
And when you check for it, use this:
if ($user->save()===true) {
// display success to user
} else {
// display error to user
}
the === operator performs a typesafe comparison, meaning that it not only checks if the value is true, but also if the type is a boolean. If the array is being returned it's handled as false.
Would be good to return array from validation function like this
$result['ACK'] = 'true';
$result['message'] = 'Success validation'];
on failure
$result['ACK'] = 'false';
$result['message'] = 'validation error message';
Now you can use this array in front end like this
if ($result['ACK']) {
//No Error
} else {
echo $result['message'];
}
Change your condition to, If true then success else return array of errors.
if ($user->save() === true) {
//display success to user
}

PHP: Run Functions Only After Checking Variable After Each

I have a series of functions that I'd like to run. At the end of each function, it either sets a variable TRUE or FALSE. What I'd like to do is break the series if the variable sets to TRUE.
For example. I have the following:
$done = false;
step1(); // Sets $done to false
step2(); // Sets $done to false
step3(); // Sets $done to true
step4(); // Because step3() set $done to true, I wan't step4() to NOT run.
Of course if step3() returns false, I'd like to keep going and run step4().
I know I'll need to use a while, switch, and/or a break. I'm just unclear on how to set this up.
Much appreciated.
It's not much clear to me, but if your functions return booleans, you can try:
step1() || step2() || step3() || step4();
The operator || only evaluate the second operand if the first is false.
it can be done by using a simple if statement if you want.
$done = false;
$done = step1(); // each function returns true or false
if (!$done)
{
$done = step2();
}
if (!$done)
{
$done = step3();
}
if (!$done)
{
$done = step4();
}
correct me if there is any mistakes.
$done = false;
function step1($done){
if($done===false){
//proceed step 2
}
else{
return;
}
}
function step2($done){
if($done===false){
//proceed step 3
}
else{
return;
}
}
function step3($done){
if($done===false){
//proceed step 4
}
else{
return;
}
}
function step4($done){
if($done===false){
//finish
}
else{
return;
}
}
Your question is not very straight forward, probably similar to the form you have so far.
You could create an array with callbacks of your functions and consume them while $done is false and there are still functions to consume:
$doFunctions = ['step1', 'step2', ... , 'stepN'];
$done = false;
while (!$done && $doFunctions)
{
$function = array_shift($doFunctions);
call_user_func($function);
}
As this shows, no switch and no break needed, because you have a simple condition here.
Another alternative would be to "make" the functions return something by wrapping it inside a closure and keep the $done as a reference (context), then return it:
$done = false;
$call = function ($function) use (&$done) {
$function();
return $done;
}
$call('step1')
|| $call('step2')
|| $call('step3')
|| $call('step4')
;
It depends a bit of what you actually need to achieve.
So perhaps my question was misunderstood, but after a while I realized that a try/catch block with exceptions was exactly what I was after. Here is roughly what I ended up doing.
First I set up my functions to throw exceptions on errors.
function step1() {
// do awesome stuff
if ($errorInStep1) {
throw new Exception('There was an error in step 1.');
}
}
function step2() {
// do awesome stuff
if ($errorInStep2) {
throw new Exception('There was an error in step 2.');
}
}
function step3() {
// do awesome stuff
if ($errorInStep3) {
throw new Exception('There was an error in step 3.');
}
}
function step4() {
// do awesome stuff
if ($errorInStep4) {
throw new Exception('There was an error in step 4.');
}
}
So now if there is an error in each of the functions, the script will throw an exception.
Then I wrap those functions in a try/catch block. The script will try to go through each statement, and if something throws and exception...it will stop right there. Perfect.
try {
step1();
step2();
step3();
step4();
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}

returned function result is confused in conditional statement

I have a class that works with database in PHP. the Add function in this class is:
function Add($post_id)
{
if(!is_numeric($post_id))
{
return 1181;
}
$query = "...";
$result = mysql_query($query, $this->link);
return $result;
}
I also have a page that gets a form data and passes them to this class. The page code is:
$result = $obj->Add($post_id);
if($result == 1181)
{
echo 'invalid';
}
else if($result)
{
echo 'success';
}
else
{
echo 'error';
}
the returned value is 1 and the output must be 'success', but i get 'invalid' message. If i swap 'invalid' and 'success' conditional statements, everything works well, but i want to know that what's this problem for?
var_dump($result); is a good starting point. in boolean context 1181 will be converted to true, so just because it prints success don't expect that it succeeded.
You probably pass the wrong post_id. Enable displaying warnings and notices. Don't use crazy magic constants, use false or throw an exception. Always check the return value of mysql_query.
If you do that I don't have to guess and you can make progress and ask meaningful questions.
Like others have pointed out in the comments, you should be using Exceptions in these types of cases. Here's an example.
function Add($post_id)
{
if(!is_numeric($post_id))
{
throw new InvalidArgumentException( 'Argument should be numeric' );
}
$query = "...";
$result = mysql_query($query, $this->link);
return $result;
}
try
{
$result = $obj->Add($post_id);
}
catch( InvalidArgumentException $e )
{
/* handle the invalid argument exception */
}
if($result)
{
echo 'success';
}
else
{
echo 'error';
}
Furthermore, if you insist on using codes for your errors, you might use this:
function Add($post_id)
{
if(!is_numeric($post_id))
{
throw new InvalidArgumentException( 'Argument should be numeric', 1181 );
}
if($post_id <= 0)
{
throw new InvalidArgumentException( 'Argument should be larger than 0', 1182 );
}
$query = "...";
$result = mysql_query($query, $this->link);
return $result;
}
try
{
$result = $obj->Add($post_id);
}
catch( InvalidArgumentException $e )
{
switch( $e->getCode() )
{
case 1181:
/* handle the invalid argument exception with code 1181 */
break;
case 1182:
/* handle the invalid argument exception with code 1182 */
break;
default:
/* handle other invalid argument exceptions */
break;
}
}
Lastly, like others have commented also, exception handling has nothing to do with, and does not interfere with preventing SQL injection.

ADODB / SQL Server mssql_execute stored procedure fails but works if debug is set to true

I am connecting to a SQL Server database from PHP using ADODB. I have several stored procedures that I have been executing just fine. The last call that I have created for some reason keeps failing. I put debug as true and it works just fine. I have no idea why this would be happening.
here is the error I get
Error: mssql_execute() [<a href='function.mssql-execute'>function.mssql-execute</a>]: stored procedure execution failed in /path/to/adodb/lib/adodb5/drivers/adodb-mssql.inc.php on line 768
Here is the method I created to pass all my stored procedures to, like I said it works fine with other stored procedures but this one and I have double checked that all the spellings of the parameters and stored procedure are correct.
protected function _getSpArray($db, $sp, array $spParams) {
try {
$stmt = $db->PrepareSP($sp);
foreach ($spParams as $param) {
$db->InParameter($stmt, $param[0], $param[1]);
}
$db->SetFetchMode(ADODB_FETCH_ASSOC);
$rs = $db->Execute($stmt);
$rsArray = array();
if (!$rs) {
echo 'No records found \n';
return;
}
else {
foreach ($rs as $k => $row) {
$rsArray[$k] = $row;
}
}
return $rsArray;
} catch (ErrorException $e) {
echo $e->getMessage();
}
}
It is failing on this line #768 of adodb5/drivers/adodb-mssql.inc.php
$rez = mssql_execute($sql[1]);
and the sql array has these values
[0] stored_procedure_name
[1] resource id='657' type='mssql statement'
I have seen the following comments on PHP.net, I changed my freetds host name to be something different then the IP address and still nothing. I am not sure about the free result since I am using adodb.
http://www.php.net/manual/en/function.mssql-execute.php#93938
I am using adodb 5.11
When you set debug as true ADODB uses other function to execute the statement. In this case function _adodb_debug_execute(&$zthis, $sql, $inputarr)
If debug is set to false ADODB uses function &_Execute($sql,$inputarr=false). When you check the source for both methods you can clearly see the difference.
<?php
function _adodb_debug_execute(&$zthis, $sql, $inputarr)
{
//ADODB prepares debug information dump...
$qID = $zthis->_query($sql,$inputarr);
//Here ADODB makes the difference
if ($zthis->databaseType == 'mssql') {
// ErrorNo is a slow function call in mssql, and not reliable in PHP 4.0.6
if($emsg = $zthis->ErrorMsg()) {
if ($err = $zthis->ErrorNo()) ADOConnection::outp($err.': '.$emsg);
}
} else if (!$qID) {
ADOConnection::outp($zthis->ErrorNo() .': '. $zthis->ErrorMsg());
}
if ($zthis->debug === 99) _adodb_backtrace(true,9999,2);
return $qID;
}
?>
Here is the _Execute function
<?php
function &_Execute($sql,$inputarr=false){
//Here ADODB chooses which fn to use
if ($this->debug) {
global $ADODB_INCLUDED_LIB;
if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR.'/adodb-lib.inc.php');
$this->_queryID = _adodb_debug_execute($this, $sql,$inputarr);
} else {
$this->_queryID = #$this->_query($sql,$inputarr);
}
//...
if ($this->_queryID === false) { // error handling if query fails
//If debug ADODB prints backtrace regardless the result
if ($this->debug == 99) adodb_backtrace(true,5);
$fn = $this->raiseErrorFn;
if ($fn) {
$fn($this->databaseType,'EXECUTE',$this->ErrorNo(),$this->ErrorMsg(),$sql,$inputarr,$this);
}
$false = false;
//Returns false no matter what...
return $false;
}
//...
}
?>
Try adding this to your script to test the behaviour of the script and keep in mind that if the execute fails it will return a false value. So take care with the returned value.
protected function _getSpArray($db, $sp, array $spParams) {
try {
$stmt = $db->PrepareSP($sp);
foreach ($spParams as $param) {
$db->InParameter($stmt, $param[0], $param[1]);
}
$db->SetFetchMode(ADODB_FETCH_ASSOC);
$rs = $db->Execute($stmt);
$rsArray = array();
if (!$rs) {
echo 'No records found \n';
return;
}
else {
foreach ($rs as $k => $row) {
$rsArray[$k] = $row;
}
}
//add this line to free the resources after use.
mssql_free_result($rs);
return $rsArray;
} catch (ErrorException $e) {
echo $e->getMessage();
}
}
Hope it helps!!
Ok, after finding the php.net comments, even though my freetds wasn't setup with the proper name, I was using the ip address. I also wasn't using the V 8.0 I was using 7.0 and everything was working fine up until this point with the store procedures. I tried the mssql_free_result solution provide in the comments and DarkThrones answer and that didn't work but when I used adodb's close() method it is working. It uses free result and passes a query id.
If someone can comment as to why this is necessary that would be great. Is it because I was using up to much memory or something?

Categories