I'm trying to create an extremely basic script that can function as a REST API. I've been having a lot of trouble getting any output to show on the page. In the code below you can see a couple of the commented methods I've tried to get an output. If I remove the printf while loop and just use the responseData = json_encode($result) line, I get a JSON output in the proper format but only containing null values. (Table columns have the appropriately named table headers but nothing else, no data is returned). For the record, the SQL statements, are being properly executed without error. The below script generates no PHP.log errors when run. If I change the SQL to an insert statement I can see the resulting values in the database. So whatever is going on here is some issue with simply outputting those values to the page.
This is the code for the entire page script I am using;
<?php
define("PROJECT_ROOT_PATH", __DIR__);
define("DB_HOST", "localhost");
define("DB_USERNAME", "testuser");
define("DB_PASSWORD", "testpw");
define("DB_DATABASE", "testgb");
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$uri = explode( '/', $uri );
/** Basic Input Filter **/
function input_filter($data) {
$data= trim($data);
$data= stripslashes($data);
$data= htmlspecialchars($data);
return $data;
}
/**
* Get URI elements.
*
* #return array
*/
function getUriSegments()
{
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$uri = explode( '/', $uri );
return $uri;
}
function sendOutput($data, $httpHeaders=array())
{
header_remove('Set-Cookie');
if (is_array($httpHeaders) && count($httpHeaders)) {
foreach ($httpHeaders as $httpHeader) {
header($httpHeader);
}
}
echo $data;
exit;
}
/**
* "/[usertoken]/read" Endpoint - retrieve orders from db
*/
function readAction()
{
$strErrorDesc = '';
$requestMethod = $_SERVER["REQUEST_METHOD"];
$arrQueryStringParams = parse_str($_SERVER['QUERY_STRING'], $query);
if (strtoupper($requestMethod) == 'GET') {
try {
$intLimit = 100;
if (isset($arrQueryStringParams['limit']) && $arrQueryStringParams['limit']) {
$intLimit = $arrQueryStringParams['limit'];
}
$intItemId = 0;
if (isset($arrQueryStringParams['itemid']) && $arrQueryStringParams['itemid']) {
$intItemId = $arrQueryStringParams['itemid'];
echo $intItemId;
}
$conn = mysqli_connect(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_DATABASE);
if ($conn->connect_error)
{
die("Connection failed: ". mysqli_connect_error());
}
$sql = "SELECT * FROM verified_orders WHERE itemid=?;";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
die("Statement preparation failed.");
} else {
mysqli_stmt_bind_param($stmt, "d", $intItemId);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
if ($row = mysqli_fetch_assoc($result)) {
while ($row = $result -> fetch_row()) {
printf ("%s (%s)\n", $row[0], $row[1]);
}
}
/*$responseData = json_encode($result);*/
}
} catch (Error $e) {
$strErrorDesc = $e->getMessage().'.';
$strErrorHeader = 'HTTP/1.1 500 Internal Server Error';
}
} else {
$strErrorDesc = 'Method not supported';
$strErrorHeader = 'HTTP/1.1 422 Unprocessable Entity';
}
// send output
if (!$strErrorDesc) {
/*echo $responseData;
} else {
echo $responseData;*/
}
}
if (isset($uri[2]) && $uri[2] != 'user') {
header("HTTP/1.1 404 Not Found");
exit();
}
if ($uri[3] == "read") {
readAction();
}
?>
Database API changes and misleading parse_str()
updated: There were a few errors going on in the end, combined with a lack of logs, resulting in a messy thread; I've updated this answer postmortem, to consolidate the solutions and realizations.
There seemed to be some problems with the database access (mixed forms of mysqli-fetching) and potentially false expectations, due to associative vs numeric results ($row[0], $row[1] were attempted in assoc mode). In the end, the entire set of Mysqli connect/prepare/query/fetch-calls were replaced with known good PDO variants; namely:
if (!($conn = new PDO(sprintf('mysql:dbname=%s;host=%s', DB_DATABASE, DB_HOST), DB_USERNAME, DB_PASSWORD, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ])))
throw new Exception('Connection failed');
if (!($stmt = $conn->prepare('
SELECT *
FROM verified_orders
WHERE itemid = :itemid
ORDER BY itemid
'))) throw new Exception('Prepare failed');
if (!$stmt->execute([ 'itemid' => $intItemId ]))
throw new Exception('Execute failed');
if (!($data = $stmt->fetchAll( PDO::FETCH_ASSOC|PDO::FETCH_GROUP|PDO::FETCH_UNIQUE )))
throw new Exception('Fetch failed');
Which is not to say that the mysqli-variants itself couldn't have been fixed. The problem just wasn't readily apparent.
The PDO database calls solved most problems, but not the absence of any value in the $intItemId variable (which is used in the SELECT query). That variable lived downstream from $arrQueryStringParams, which in turn was ment to be set here:
$arrQueryStringParams = parse_str($_SERVER['QUERY_STRING'], $query);
At first glance this looked fine, however the parse_str() function produces no return value. It actually injects the results into the 2nd argument, which in this case was a stray variable called $query (which wasn't used anywhere else at all).
The proper syntax for parse_str() would be:
parse_str($_SERVER['QUERY_STRING'], $arrQueryStringParams);
Original attempts at a solution
You're using mysqli_fetch_assoc to fetch the query results (note the associative).
This means the results won't end up in $row[0], $row[1], ... But instead $row is an associative array based on the column names, such as $row['itemid'].
offtopic note: you should remove the ; at the end of your SQL query. It can be a part of a SQL script command , where it denotes the end of a statement, but it isn't considered part of a single query.
update
Try replacing
$result = mysqli_stmt_get_result($stmt);
if ($row = mysqli_fetch_assoc($result)) {
while ($row = $result -> fetch_row()) {
printf ("%s (%s)\n", $row[0], $row[1]);
}
}
with
while ($row = $result->fetch_array(MYSQLI_BOTH)) {
printf ("%s (%s)\n", $row[0], $row[1]);
}
See if that fixes the problem.
if it does not then check the logfiles and show the output of var_dump($x) for $row, $result, $stmt and $conn.
And then repeat that process again after replacing the SQL with:
$sql = "SELECT 123 AS num, 'abc' AS str, ? AS inputval";
update 2
Weird results, without anything to go on debugging wise, its probably best to try the following. (Temporarily) remove all your code starting at the line:
/** Basic Input Filter **/
and from there, all the way to the end of the file. Basically only leaving your defines; and then copy/paste the following at the bottom of the file, and then try to visit the page in your webbrowser, see what it prints.
try {
echo 'A';
if (!($conn = new PDO(sprintf('mysql:dbname=%s;host=%s', DB_DATABASE, DB_HOST), DB_USERNAME, DB_PASSWORD, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ])))
throw new Exception('Connection failed');
echo 'B';
if (!($stmt = $conn->prepare('
SELECT *
FROM verified_orders
WHERE itemid = :itemid
OR 1=1
ORDER BY itemid
LIMIT 20
'))) throw new Exception('Prepare failed');
echo 'C';
if (!$stmt->execute([ 'itemid' => 1 ]))
throw new Exception('Execute failed');
echo 'D';
if (!($data = $stmt->fetchAll( PDO::FETCH_ASSOC|PDO::FETCH_GROUP|PDO::FETCH_UNIQUE )))
throw new Exception('Fetch failed');
echo 'E';
echo PHP_EOL . '<br>';
var_dump( $data );
echo PHP_EOL . '<br>';
echo 'F';
} catch (Throwable $e) { echo PHP_EOL . '<br>Exception: ' . htmlentities($e->getMessage()); }
Exit(0);
Related
I have an old PHP code that has mysql in it.
It gets an array from a SELECT statement, adds it to a JSON object, as a property and echoes the encoded JSON.
I changed it around to use mysqli, but when I try to get the rows, and create an array out of them, it just returns nothing.
Here's the old mysql code:
$con = mysql_connect('host','account','password');
if (!$con)
{
//log my error
};
mysql_select_db("database_name", $con);
mysql_set_charset('utf8');
$sql = "SELECT field1 as Field1, field2 as Field2 from table where ID = '".$parameter."'";
$query = mysql_query($sql);
$results = array();
while($row = mysql_fetch_assoc( $query ) )
{
$results[] = $row;
}
return $results;
Version1: Here's the new one that I tried writing:
$con = mysqli_connect('host','account','password','database_name');
$sql = "SELECT field1 as Field1, field2 as Field2 from table where ID = '".$parameter."'";
$results = array();
if($result=mysqli_query($con, $sql))
{
while ($row=mysqli_fetch_assoc($result))
{
$results[] = $row;
}
return $results;
}
else
{
//error
}
Version2: Second thing I tried, which only returns 1 ROW:
...same as above until $sql
if($result=mysqli_query($con,$sql))
{
$row=mysqli_fetch_assoc($result);
return $row;
}
Version3: Or I tried to completely mirror the mysql structure like this:
$sql = "SELECT ...";
$query = mysqli_query($con, $sql);
$results = array();
while($row = mysqli_fetch_assoc( $query ) )
{
$results[] = $row;
}
return $results;
Wrapping the resulting array into the JSON:
$obj = new stdClass();
$obj->Data = $results;
$obj->ErrorMessage = '';
die(json_encode($obj)); //or echo json_encode($obj);
None of the mysqli version are working, so I was thinking there might be an important change in the way these arrays are created.
Any tips on what could be wrong on the first mysqli example?
With Version2 I can tell that the SQL connection is there, and I can at least select a row. But it's obviously only one row, than it returns it. It makes me think, that building up the array is the source of the problem, or it's regarding the JSON object...
LATER EDIT:
OK! Found a working solution.
ALSO, I played around with the data, selected a smaller chunk, and it suddenly worked. Lesson from this: the function is not responding the same way for 40 rows or for 5 rows. Does it have something to do with a php.ini setting? Or could there be illegal characters in the selection? Could it be that the length of a 'Note' column (from the db) is too long for the array to handle?
Here's the working chunk of code, that selects some rows from the database, puts them into an array, and then puts that array into an object that is encoded into JSON at the end, with a statusmessage next to it. Could be improved, but this is just for demo.
$con = mysqli_connect('host','username','password','database_name');
if (!$con)
{
$errorMessage = 'SQL connection error: '.$con->connect_error;
//log or do whatever.
};
$sql = "SELECT Field1 as FieldA, field2 as FieldB, ... from Table where ID='something'";
$results = array();
if($result = mysqli_query($con, $sql))
{
while($row = mysqli_fetch_assoc($result))
{
$results[] = $row;
}
}
else
{
//log if it failed for some reason
die();
}
$obj->Data = $results;
$obj->Error = '';
die(json_encode($obj));
Question is: how can I overcome the issue regarding the size of the array / illegal characters (if that's the case)?
Your "Version 1" seems to be correct from a PHP perspective, but you need to actually handle the errors - both when connecting and when performing the query. Doing so would have told you that you don't actually query a table, you're missing FROM tablename in the query.
Use mysqli_connect_error() when connecting, and mysqli_error($con) when querying to get back the actual errors. General PHP error-reporting might also help you.
The code below assumes that $parameter is defined prior to this code.
$con = mysqli_connect('host','account','password','database_name');
if (mysqli_connect_errno())
die("An error occurred while connecting: ".mysqli_connect_error());
$sql = "SELECT field1 as Field1, field2 as Field2
FROM table
WHERE ID = '".$parameter."'";
$results = array();
if ($result = mysqli_query($con, $sql)) {
while ($row = mysqli_fetch_assoc($result)) {
$results[] = $row;
}
return $results;
} else {
return mysqli_error($con);
}
Error-reporing
Adding
error_reporting(E_ALL);
ini_set("display_errors", 1);
at the top of your file, directly after <?php would enable you to get the PHP errors.
NOTE: Errors should never be displayed in a live environment, as it might be exploited by others. While developing, it's handy and eases troubleshooting - but it should never be displayed otherwise.
Security
You should also note that this code is vulnerable to SQL-injection, and that you should use parameterized queries with placeholders to protect yourself against that. Your code would look like this with using prepared statements:
$con = mysqli_connect('host','account','password','database_name');
if (mysqli_connect_errno())
die("An error occurred while connecting: ".mysqli_connect_error())
$results = array();
if ($stmt = mysqli_prepare("SELECT field1 as Field1, field2 as Field2
FROM table
WHERE ID = ?")) {
if (mysqli_stmt_bind_param($stmt, "s", $parameter)) {
/* "s" indicates that the first placeholder and $parameter is a string */
/* If it's an integer, use "i" instead */
if (mysqli_stmt_execute($stmt)) {
if (mysqli_stmt_bind_result($stmt, $field1, $field2) {
while (mysqli_stmt_fetch($stmt)) {
/* Use $field1 and $field2 here */
}
/* Done getting the data, you can now return */
return true;
} else {
error_log("bind_result failed: ".mysqli_stmt_error($stmt));
return false;
}
} else {
error_log("execute failed: ".mysqli_stmt_error($stmt));
return false;
}
} else {
error_log("bind_param failed: ".mysqli_stmt_error($stmt));
return false;
}
} else {
error_log("prepare failed: ".mysqli_stmt_error($stmt));
return false;
}
References
http://php.net/mysqli.prepare
How can I prevent SQL injection in PHP?
I have a PDO that is querying a non-existant user in the database to handle user registration. The problem is, var_dump and print_r both do not print anything if the user is not found.
try {
$stmt->execute();
while($row = $stmt->fetch()) {
var_dump($row);
print_r($row);
if($row = null) { // Not working
# if(!isset($row)) { // Not working
# if(empty($row)) { // Also not working
echo "User not found";
} else {
echo $row['realname']."<br>";
}
}
} catch(PDOException $e) {
echo "FATAL ERROR OCCURED:".$e->getMessage();
}
What is happening here? The page is just blank.
php -l index.php repors no syntax errors and the page is not throwing error 500.
Nothing in view source either.
Here is connection details:
try {
$dbh = new PDO('mysql:host=127.0.0.1;dbname=PHP_PDO', "root", "root", array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));
} catch(PDOException $e) {
die("FATAL ERROR OCCURED");
}
$stmt = $dbh->prepare("SELECT realname FROM users WHERE name = :name" );
$stmt->bindParam(":name", $name);
$name = "mivuckovaca"; // NOT IN DATA BASE
The reason why it's not working, is that you are "assigning" in if($row = null) using 1 equal sign, rather than "comparing" if($row == null) with 2 equal signs (or 3 "if identical", depending on what you want to check for).
Consult: The 3 different equals here on Stack about this.
References:
http://php.net/manual/en/language.operators.assignment.php
http://php.net/manual/en/language.operators.comparison.php
PHP sees the "assignment" as being valid syntax and that is why you are not receiving any errors.
Turns out i had to reorganize the code a bit.
I took the $row = $stmt->fetch(); out of the while loop, and checked the $row seperately. Like this:
$stmt = $dbh->prepare("SELECT realname FROM users WHERE name = :name" );
$stmt->bindParam(":name", $name);
$name = "mivuckovaca"; // NOT IN DATABSE ON PURPOSE
try {
$stmt->execute();
} catch(PDOException $e) {
echo "FATAL ERROR OCCURED:".$e->getMessage();
}
$res = $stmt->fetchAll(); # Replaced fetch() with fetchAll()
if(empty($res)) {
echo "User not found";
} else {
foreach($res as $row) { # replaced while() with foreach()
echo $row['realname'];
}
}
I have a reasonably complicated stored procedure in MSSQL 2008 R2 that, in the end, results in a small table being returned. The PHP will be called from javascript and I want it to return the array as JSON to be used in table in the javascript.
I am using PHP to access it and, using the profiler, can see that I am calling the SP and passing the correct parameters to it.
My PHP looks like this:
try {
$dbh = new PDO("sqlsrv:Server=(local);Database=cddDispo");
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo json_encode("Error connecting to the server.");
die ();
}
$lot = $_POST["lot-input"];
$layerAdder = $_POST["layer-input"];
$adder = substr($layerAdder,-3,3);
$adder = str_replace('=','',$adder);
$layer = substr($layerAdder,0,strpos($layerAdder,' '));
$sth = $dbh->prepare('EXEC dbo.pullDispo ?,?,?');
$sth->bindParam(1,$lot,PDO::PARAM_STR);
$sth->bindParam(2,$layer,PDO::PARAM_STR);
$sth->bindParam(3,$adder,PDO::PARAM_STR);
$array = array();
try {
$sth->execute();
while($row = $sth->fetch(PDO::FETCH_ASSOC)) {
//I want to build my output array here
}
}catch (PDOException $e) {
echo "Error getting data, please try again.";
die();
}
header('Content-type: application/json');
echo json_encode($array);
This is the first time that I have tried to return table results from a stored procedure and even with several PHP Manual/ Google searches I have not figured out how to capture the table back in the PHP. I have a less elegant workaround (write the SP table to a static table and call that table later in the PHP) but would rather figure out if I can do in a more elegant manner. Any advice is much appreciated.
I thought it might be useful if I posted my final code:
function array_push_assoc($array,$key,$value) {
$array[$key] = $value;
return $array;
}
header('Content-type: application/json');
try {
$dbh = new PDO('sqlsrv:Server=(local);Database=cddDispo');
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo json_encode('Error connecting to the server.');
die ();
}
$lot = $_POST['lot'];
$layer = $_POST['layer'];
$adder = $_POST['adder'];
$sth = $dbh->prepare('EXEC dbo.pullDispo ?,?,?');
$sth->bindParam(1,$lot,PDO::PARAM_STR);
$sth->bindParam(2,$layer,PDO::PARAM_STR);
$sth->bindParam(3,$adder,PDO::PARAM_STR);
$results = array();
$combinedArray = array();
$array = array();
$count = 0;
try {
$sth->execute();
do {
$results[] = $sth->fetchAll(PDO::FETCH_ASSOC);
}while ($sth->nextRowset());
foreach($results as $row) {
if($count == 0) {
$headerArray =
[
'Lot' =>$row['Lot'],
'Layer' =>$row['Measured Layer'],
'Product' =>$row['MES Product'],
'Adder' =>$row['Adder Chart']
];
$combinedArray = array_push_assoc($combinedArray,'header',$headerArray);
}
$count++;
//This is for formatting of final table
if($row['UDL'] == 0) {
$udl = 'NA';
} else {
$udl = round($row['UDL'],4);
}
$infoArray =
[
'Wafer' =>$row['Wafer'],
'Type' =>$row['Type'],
'Count' =>$row['Count'],
'CDD' =>round($row['CDD'],3),
'UCL' =>round($row['UCL'],4)
];
array_push($array,$infoArray);
}
$combinedArray = array_push_assoc($combinedArray,'detail',$array);
}catch (PDOException $e) {
echo json_encode('Error running stored procedure.');
die();
}
echo json_encode($combinedArray);
Could it be that your stored procedure is returning multiple result sets? This includes output like warning messages or number of rows affected. Try adding SET ANSI_WARNINGS OFF or SET NOCOUNT ON at the top of your stored procedures after the AS. You can also try advancing to the next result set in PHP before trying to get the results by calling $stg->nextRowset() before $sth->fetchAll().
Use fetchAll() to get your resultset, then encode that array as your json response:
$array = array();
try {
if($sth->execute()){
$array = $sth->fetchAll(PDO::FETCH_ASSOC);
}else{
$array = array('error'=>'failed to execute()')
}
}catch (PDOException $e) {
echo "Error getting data, please try again.";
die();
}
header('Content-type: application/json');
echo json_encode($array);
When you are calling a stored procedure with multiple result sets, you probably do not want to add SET NOCOUNT ON into every procedure you have; you always can add
$dbh->setAttribute(constant('PDO::SQLSRV_ATTR_DIRECT_QUERY'), true);
$dbh->query("SET NOCOUNT ON");
before of
$dbh->prepare($query);
and it will work.
Scenario:
I have a SQL Query INSERT INTO dbo.Grades (Name, Capacity, SpringPressure) VALUES ('{PHP}',{PHP}, {PHP})
The data types are correct.
I need to now get the latest IDENTIY which is GradeID.
I have tried the following after consulting MSDN and StackOverflow:
SELECT SCOPE_IDENTITY() which works in SQL Management Studio but does not in my php code. (Which is at the bottom), I have also tried to add GO in between the two 'parts' - if I can call them that - but still to no avail.
The next thing I tried, SELECT ##IDENTITY Still to no avail.
Lastly, I tried PDO::lastInsertId() which did not seem to work.
What I need it for is mapping a temporary ID I assign to the object to a new permanent ID I get back from the database to refer to when I insert an object that is depended on that newly inserted object.
Expected Results:
Just to return the newly inserted row's IDENTITY.
Current Results:
It returns it but is NULL.
[Object]
0: Object
ID: null
This piece pasted above is the result from print json_encode($newID); as shown below.
Notes,
This piece of code is running in a file called save_grades.php which is called from a ajax call. The call is working, it is just not working as expected.
As always, I am always willing to learn, please feel free to give advice and or criticize my thinking. Thanks
Code:
for ($i=0; $i < sizeof($grades); $i++) {
$grade = $grades[$i];
$oldID = $grade->GradeID;
$query = "INSERT INTO dbo.Grades (Name, Capacity, SpringPressure) VALUES ('" . $grade->Name . "',". $grade->Capacity .", ".$grade->SpringPressure .")";
try {
$sqlObject->executeNonQuery($query);
$query = "SELECT SCOPE_IDENTITY() AS ID";
$newID = $sqlObject->executeQuery($query);
print json_encode($newID);
} catch(Exception $e) {
print json_encode($e);
}
$gradesDictionary[] = $oldID => $newID;
}
EDIT #1
Here is the code for my custom wrapper. (Working with getting the lastInsertId())
class MSSQLConnection
{
private $connection;
private $statement;
public function __construct(){
$connection = null;
$statement =null;
}
public function createConnection() {
$serverName = "localhost\MSSQL2014";
$database = "{Fill In}";
$userName = "{Fill In}";
$passWord = "{Fill In}";
try {
$this->connection = new PDO( "sqlsrv:server=$serverName;Database=$database", $userName, $passWord);
$this->connection->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch( PDOException $e ) {
die("Connection Failed, please contact system administrator.");
}
if ($this->connection == null) {
die("Connection Failed, please contact system administrator.");
}
}
public function executeQuery($queryString) {
$results = array();
$this->statement = $this->connection->query( $queryString );
while ( $row = $this->statement->fetch( PDO::FETCH_ASSOC ) ){
array_push($results, $row);
}
return $results;
}
public function executeNonQuery($queryString) {
$numRows = $this->connection->exec($queryString);
}
public function getLastInsertedID() {
return $this->connection->lastInsertId();
}
public function closeConnection() {
$this->connection = null;
$this->statement = null;
}
}
This is PDO right ? better drop these custom function wrapper...
$json = array();
for ($i=0; $i < sizeof($grades); $i++) {
//Query DB
$grade = $grades[$i];
$query = "INSERT INTO dbo.Grades (Name, Capacity, SpringPressure)
VALUES (?, ?, ?)";
$stmt = $conn->prepare($query);
$success = $stmt->execute(array($grade->Name,
$grade->Capacity,
$grade->SpringPressure));
//Get Ids
$newId = $conn->lastInsertId();
$oldId = $grade->GradeID;
//build JSON
if($success){
$json[] = array('success'=> True,
'oldId'=>$oldId, 'newId'=>$newId);
}else{
$json[] = array('success'=> False,
'oldId'=>$oldId);
}
}
print json_encode($json);
Try the query in this form
"Select max(GradeID) from dbo.Grades"
Using the code below, I get the error, "Call to undefined method stdClass::fetchObject()".
function getProdDetails2SaveInInvoice($data) {
global $dbh;
try {
$sth=$dbh->prepare("
SELECT
AES_DECRYPT('alt_id', ?),
AES_DECRYPT('prod_name', ?),
AES_DECRYPT('prod_desc', ?)
FROM
products
WHERE
prod_id = ?
");
$sth->execute($data);
$rs = $sth->query(PDO::FETCH_ASSOC);
return $rs;
}
catch(PDOException $e) {
echo "Something went wrong. Please report this error.\n";
file_put_contents(
$_SERVER['DOCUMENT_ROOT']."/PDOErrors.txt",
"\n\nScript name : ".SCRIPT."\nFunction name : ".__FUNCTION__."\n".
$e->getMessage(), FILE_APPEND);
throw new failedTransaction();
}
}
$data = array(
DBKEY, /* field 1 */
DBKEY, /* field 2 */
DBKEY, /* field 3 */
$prodid /* comparison */
);
$rs = getProdDetails2SaveInInvoice($data);
while ($row = $rs->fetchObject()) {
echo $row->prod_name;
}
Unfortunately, this doesn't work and returns the error mentioned above.
I can confirm that the $dbh database connection is working as it's the same connection working for the inserts and updates. Thanks.
UPDATE
This is how I've amended my code based on the suggestions below, but I'm still getting nothing returned:
try {
$dbh = new PDO("mysql:host=".CO_DB_HOST.";dbname=".CO_DB_NAME, CO_DB_UNAME, CO_DB_PWORD);
$dbh ->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch(PDOException $e) {
echo $e->getMessage();
}
function getProdDetails2SaveInInvoice($data) {
global $dbh;
try {
$sth=$dbh->prepare("
SELECT
AES_DECRYPT('alt_id', ?),
AES_DECRYPT('prod_name', ?),
AES_DECRYPT('prod_desc', ?)
FROM
products
WHERE
prod_id = ?
");
$sth->execute($data);
while ($row = $sth->fetchObject()) {
// PROCESS ROW
$rs = array($row->alt_id, $row->prod_name, $row->prod_desc);
}
return $rs;
}
catch(PDOException $e) {
echo "Something went wrong. Please report this error.\n";
file_put_contents(
$_SERVER['DOCUMENT_ROOT']."/PDOErrors.txt",
"\n\nScript name : ".SCRIPT."\nFunction name : ".__FUNCTION__."\n".
$e->getMessage(), FILE_APPEND);
throw new failedTransaction();
}
}
// Fetch additional info from invoice_products.
$data = array(
DBKEY, /* field 1 */
DBKEY, /* field 2 */
DBKEY, /* field 3 */
$prodid /* comparison */
);
$rs = getProdDetails2SaveInInvoice($data);
print_r($rs);
If I hardcode the 'where' argument (19), it still does not retrieve the result. Ideally I think I should retrieve the result in an object so that it can be streamed, but right now, I'd be happy even if it came in a box!
The data is definitely existing in the database and can be pulled using a traditional query.
This is the output of the print_r($rs):
Array
(
[0] =>
[1] =>
[2] =>
)
You should loop over the prepared statement, and not call query on the prepared statement. Basic usage of prepared statements is as follows:
$sth = $dbh->prepare("YOUR QUERY");
$sth->execute();
$results = array();
while ($row = $sth->fetchObject()) {
$results[] = array(
'alt_id' => $row->alt_id,
'prod_name' => $row->prod_name,
'prod_desc' => $row->prod_desc
);
}
return $result;
As an alternative you could also use $sth->fetchAll() which returns an array with all rows that are the result of your query, see PDOStatement::fetchAll().