Getting the results of a variable length prepared statement in MySQLi - php

I writing an accounting website which has quite a few MySQL statements in it. To prevent SQL injection I use prepared statements for any data which is put in by the user.
In order to prevent having to write the steps of preparing and binding statements I have the following function:
function executeSql($mysqli,$query_string,$params=null,$paramtypes=null){
$nr_params=strlen($paramtypes);
$query_type = substr($query_string,0,3);
$stmt = $mysqli->prepare($query_string);
$queryParams[] = $paramtypes;
$counter=1;
if($nr_params>1){
while($counter<=$nr_params){
$queryParams[$counter]=&$params[$counter-1];
$counter++;
}
} else {
$queryParams[1]=&$params;
}
// Actual binding of the statement. Taking into account a variable numbers of '?' in the query string.
call_user_func_array(array($stmt,'bind_param'),$queryParams);
// Execution of the statement
$stmt->execute();
// Part where i'd like to have a substitute for:
$result = $stmt->get_result();
return $result;
}
In the last part I'd like to return the result because then using the result I can treat each row. The problem is that the mysqlnd driver is not installed on the production server so the function $stmt->get_result() cannot be used. I tried to bind the result into variables but then again, every query returns a different number of columns.
Anyone has an idea how to tackle this?
So in summary (in response to the comments):
How can I retrieve a results object of an executed MySQLi statement while I cannot use $stmt->get_result();
Kind regards,
EJG
PS I know the code is not flawless, e.g. if strings are used as variables to bind to the statement but that is easily fixed.
UPDATE:
I came across the function $stmt->result_metadata(); Although supposedly the function name suggests only the meta data the php documentation states that:
"If a statement passed to mysqli_prepare() is one that produces a result set, mysqli_stmt_result_metadata() returns the result object"...

Related

Do i need a "return" statement when using fetchAll() in a function?

I'm testing in PHP a simple function to take data in a faster way, simply putting a query argument and creating an array using fetchAll().
Since fetchAll() is returning an array, do I need the "return" statement or not?
PHP
function data_extraction($query) {
$query = $co->prepare($sql);
$query->execute()->fetchAll(PDO::FETCH_ASSOC);
// do I need "return $query"?;
}
Based on your comment that:
i'm using this function to extract some results that i need to use later in the program
It does sound like you need to return the results of fetchAll() from the function.
This is easily achieved:
function data_extraction($sql) {
$query = $co->prepare($sql);
$query->execute();
$arr = $query->fetchAll(PDO::FETCH_ASSOC);
return $arr;
}
This will return the array produced by fetchAll() to callers of your function.
Note: You probably don't want to return $query as this will give an outside caller access to your prepared statement.
To utilise in your code:
...
$results = data_extraction('SELECT xyz...');
Replacing the SELECT xyz... statement with your chosen SQL statement.
NOTE
Following an important comment by #YourCommonSense regarding parameterisation of PDO prepared statements, I urge extreme caution when injecting user content into SQL statements without the use of parameters. The reference provided by #YourCommonSense is here which has a glorious description of the issue and how to resolve it.
This answer is to primarily address the question Do I use a return statement? not How do I safely use PDO prepared statements

MySQLi prepared statement fails where identical regular query succeeds

I have a conventional query that works just fine that looks like this:
$result = $mysqli->query("SELECT value FROM activities WHERE name = 'Drywall'");
This succeeds in returning a row. However, for the purposes of diagnosing the problem I'm having with a prepared statement, I tried an identical query as a prepared statement like so:
$stmt = $mysqli->prepare("SELECT value FROM activities WHERE name = 'Drywall'");
$stmt->execute();
Despite the fact these are identical query strings, $stmt->num_rows is always 0. Why would the conventional query work, but the prepared statement not when they are the same exact query? Also, I realize including 'Drywall' in the prepared query string runs counter to the purpose of prepared statements, but I was just trying to eliminate the possibility that bind_param() was the culprit. So I was using bind_param() to fill in placeholders and that wasn't working either, despite my double-checking at runtime that the variable I was binding contained the correct value.
I think you want to use
$stmt->store_result();
before the call
$stmt->num_rows();
see last line of the descripton in the manual for $stmt->num_rows() (http://www.php.net/manual/en/mysqli-stmt.num-rows.php).
Check for proper use of the mysqli->prepare. The function depends on a parameter to be passed. It is different from passing the values ​​directly in the query but can use with another way.
Verify the manual:
http://www.php.net/manual/pt_BR/mysqli.prepare.php
Did you try something like this:
$stmt = $mysqli->prepare("SELECT value FROM activities WHERE name = 'Drywall'");
$stmt->execute();
$res = $stmt->get_result();
$row = $res->fetch_assoc();
PS:
Prepared statements are Good. I would urge you to ALWAYS consider using them.
But in this case, a simple query would be much more efficient (would incur fewer round trips) than a prepared statement.

return all data in a mysql table with prepared statement

I want to return all information on the offers table.
$sth = $mysqli->prepare('SELECT * from offers');
$sth->execute();
$resultex = $sth->fetch();
$sth->close();
return json_encode($resultex);
But this doesn't work. How do I do that with prepared statement in mysqli?
I do not want to use PDO in this case.
fetch and friends return a single row of the result set. Also, fetch uses bind variables, so you need a different scheme for obtaining your results. get_result and fetch_array will most likely work for you.
You need to loop over the rows, something like this:
$sth->execute();
while ($row = $sth->fetch_array(MYSQLI_NUM))
{
foreach ($row as $r)
{
/* do your json encoding for the present row */
}
}
$sth->close();
You probably need to bind your results to variables. See the documentation here. You'll need to do something like this:
/* bind result variables */
$sth->bind_result($var1, $var2, $var3);
while ($sth->fetch()) {
$intermediateVariable[] = array($var1, $var2, $var3);
}
Let's set this straight, a few things:
You don't need to use a prepared statement in this case!
Prepared statements are great when you have parameters. The golden rule: If you have variables in your query (even if they're constant, mind you), you need prepared statements. If you don't have them, you don't need prepared statements.
You want all of the information, but you only fetch once
mysqli_statement::fetch() will only fetch one row. If you want more, you need to use a while loop.
You are returning but it doesn't look like you're in a function
Are you? return doesn't output anything. So outside of a function/method scope, you won't get anything out of return in that context.

PDO and executing code

Just a quick question around executing PDO statements.
Below is my query
$setDate = "INSERT INTO wl_datecheck (inputdate) VALUES (UNIX_TIMESTAMP(STR_TO_DATE($reportDate, '%Y%m%d')))";
Now, what I am doing is setting the query & connection as the variable $data as follows:
$data = $conn->query($setDate);
What I need to know, is does that ^^ alone execute or do I need to include
$data->execute();
The reason for asking is that I seem to be getting duplicate content from the INSERT statement & I'm not sure why
You are indeed doing it twice, you either use Query or Execute.
From the Docs:
PDO::query() executes an SQL statement in a single function call,
returning the result set (if any) returned by the statement as a
PDOStatement object.
For a query that you need to issue multiple times, you will realize
better performance if you prepare a PDOStatement object using
PDO::prepare() and issue the statement with multiple calls to
PDOStatement::execute().
http://us2.php.net/pdo.query
You can also simply check the result of the Insert statement by using rowCount()
$data = $conn->query($setDate);
if($data->rowCount() >= 1){
//echo "Inserted";
}else{
//echo "An error occurred while inserting";
//$arr = $data->errorInfo();
//print_r($arr);
}
And no need to call execute()

I Can Never Execute SQL-Safe Queries?

I am using the ODBC extension in PHP to connect to an SQL 2000 server. Here is what I am up against:
I can execute queries with odbc_exec() OR
I can execute queries with odbc_execute()
In my opinion, the differences between these two query executing methods are nearly as different as night and day:
odbc_exec() will execute a non SQL-safe query and return the results from the query
odbc_execute() is used in conjunction with odbc_prepare() to execute an SQL safe query on the database. However, odbc_execute() can only ever return a boolean, and therefore cannot be used to return the results from a SELECT statement, or to check how many rows were updated from an UPDATE or DELETE statement
Is this really the way this all works, or is there some way to escape values for use in odbc_exec() or to get the results back from odbc_execute()?
The PHP documentation doesn't seem to over any solutions for the above dilemma.
Thank you for your time.
The resource for the query you're running is returned by the odbc_prepare function, not odbc_execute.
These two blocks of code do the same thing:
$query=odbc_exec("SELECT * FROM table WHERE userinput=".$hopefully_escaped_user_input);
while($row=odbc_fetch_array($query) {
//do stuff with $row
}
$query=odbc_prepare("SELECT * FROM table WHERE userinput=?");
odbc_execute($query,Array($user_input);
while($row=odbc_fetch_array($query) {
//do stuff with $row
}
Prepared statements are used in conjuction with a resource that "points to" the prepared statement.
Imagine prepared statements as if they were a function/ procedure you defined in SQL and then you use the resource to "call" that function.
Example from here:
<?php
$res = odbc_prepare($db_conn, $query_string);
if(!$res) die("could not prepare statement ".$query_string);
if(odbc_execute($res, $parameters)) {
$row = odbc_fetch_array($res);
} else {
// handle error
}
?>

Categories