How to Prepare SQL Stored Procedure Call with Parameters in PHP - php

I have a stored procedure written in SQL. I would like to make a call to it from PHP, however I want to be certain that my call is completely secure as the call includes user-inputted parameters. My stored procedure is like this:
CREATE PROCEDURE `myProcedure`(
userId INT
)
BEGIN
SELECT * FROM `users` WHERE `users`.`userId`=userId;
END
It works when I do this:
mysqli_query($mysqli_link, "CALL myProcedure(".$userinput.");");
I could use mysqli_real_escape_string:
mysqli_query($mysqli_link, "CALL myProcedure(".mysqli_real_escape_string($mysqli_link, $userinput).");");
Is this enough? I tried to use mysqli prepared statements, like this:
$stmt = mysqli_prepare($mysql_link, 'call '.$procedureName.'('.rtrim(str_repeat('?,',count($parameters)), ',').')');
call_user_func_array('mysqli_stmt_bind_param', array_merge(array($stmt, str_repeat('s', count($parameters))), refValues($parameters)));
mysqli_stmt_execute($stmt);
call_user_func_array('mysqli_stmt_bind_result', array_merge(array($stmt), refValues($parameters)));
$array = array();
while(mysqli_stmt_fetch($stmt)){
$array[] = $parameters;
}
Note: this code is written generically because it is used to access multiple different stored procedures with varying numbers of arguments. Currently it doesn't work as a number of different errors and warnings are output. Is all of this necessary? Or can I simply use mysqli_real_escape_string like above?
Thank you,
--

Related

bind_param function is not doing anything

I am trying to use the mysqli prepare and bind_param but it is not working. The bind_param function is not doing anything, not returning any error, and pauses execution of the rest of my codes. My codes are as follows:
$set = mysqli_fetch_array($sett);
$vxemail = $_SESSION['email'];
$profv = $flash->prepare("SELECT * FROM `user` WHERE `email`=:em");
$profv->bind_param(':em',$vxemail);
If you need named query parameters like :em then you should use PDO, not mysqli.
PDO supports both named parameter placeholders and positional parameter placeholders. This is handy because some databases like Oracle normally support only named placeholders, while MySQL supports only positional placeholders. PDO translates one style to the other transparently, so you can use both.
(Just don't mix different types of placeholders in the same query. Choose one style or the other.)
I prefer PDO for reasons like this. It has a lot of nice features that make it better than Mysqli.
use this code
$set = mysqli_fetch_array($sett);
$vxemail = $_SESSION['email'];
$profv = $flash->prepare("SELECT * FROM user WHERE email=?");
$profv->bind_param('s', $vxemail);
bind_param accepts the first parameter type, and then the transmitted data.
for example:
$profv->bind_param('ssid', $name, $lastname, $age, $amount);
s = string, i = integer, d = double

How to prevent SQL injection in Codeigniter [duplicate]

Hi all I need to use Prepared Statements in my site. I tried use this
$sql = "SELECT * FROM tbl_user WHERE uid=:id and activation_key=:key";
$query = $this->db->query(
$sql,
array( ':id' => $uid ,':key' => $activation_key)
);
but this is not working. When I change :id and :key to ? its working.
CodeIgniter does not support Prepared Statements. If you look at the sourcecode for CI's Database class, you will see that they resolve bindings simply by replacing the question marks with the data from the passed array:
https://github.com/EllisLab/CodeIgniter/blob/develop/system/database/DB_driver.php#L874
They only support Query Binding with unnamed placeholders. See http://ellislab.com/codeigniter/user-guide/database/queries.html
Query Bindings
Bindings enable you to simplify your query syntax by letting the system put the queries together for you. Consider the following example:
$sql = "SELECT * FROM some_table WHERE id = ? AND status = ? AND author = ?";
$this->db->query($sql, array(3, 'live', 'Rick'));
The question marks in the query are automatically replaced with the values in the array in the second parameter of the query function.
and http://ellislab.com/forums/viewthread/105112/#528915
Even though CI doesn’t support prepared statements, it does support Query Bindings. With prepared statements you have to call some type of prepare() function and then some type of execute() function. With query bindings, you only have to call one function and it basically does the same thing. Because of this, I like query bindings better than prepared statements.
On a sidenote, changing ? to :foo is merely changing from unnamed to named bindings (which CI apparently does not support either). Just because you use either or doesn't mean you are preparing the statements.
I came across this question as I faced a similar issue. The answer is correct that CI doesn't support prepared statements. However it doesn't mean that you can't use prepared statements!
In the following example I am using PDO as my connection class but the following code will work:
$q = $this->db->conn_id->prepare('SELECT * FROM tbl_user WHERE uid=? and activation_key=?');
$q->execute(array($param1,$param2));
print_r($q->fetchAll());
Note the conn_id is the PDO object against which you can run your prepared statements.
What this won't allow however is for you to get the query string which the native CI functions allow. You will need something like Get Last Executed Query in PHP PDO for that.
Further more however this doesn't stop you using the Query Builder to build your statements which you can then use in the PDO prepare. For example -
$db->where('uid = ?',null,false);
$db->where('activation_key = ?',null,false);
$q = $this->db->conn_id->prepare($db->get_compiled_select('tbl_user'));
Would build the query and would allow you to see the basic query if you output $db->get_compiled_select('tbl_user');
As #site80443 points out, CI4 now supports prepared statements and this can be found here:
https://codeigniter.com/user_guide/database/queries.html?highlight=prepared#prepared-queries

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.

PDO bind parameters

I'm building simple query builder, and I have two questions:
Is it possible to secure mysql queries with normal functions to the similar level as it is done using ->execute(array(':param:' => ... ?
Is it possible to use many variables in one query, give them the same names (the ones after the semicolon), and then bind them one by one?
If I understand you correctly, you would like to know if it possible to replicate the functionality of bindParam with the standard mysql_* functions?
Short answer is no. Please do not use the mysql functions at all, use mysqli or PDO as these provide you with the true security when it comes to prepared statements. They can also provide much better query performance as the SQL is able to be pre-optimised for the database.
You will have to define each parameter separately (even if it is the same value). You could also pass a simple array to the execute() method call, but you do not then have the option to explicitly define the parameter types.
Within your function use some thing like this:
$name = "fred";
$statement = $pdo->prepare("SELECT id FROM contacts WHERE first_name = ? OR last_name = ?");
for ($x = 1; $x <= 2; $x++) {
$statement->bindParam($x, $name, PDO::PARAM_STR);
}
$statement->execute();

mysqli prepared statement with fetch_assoc

my goal here is to be able to get a variable (with php) and use it in a prepared statement (with mysqli), and then fetch_assoc. For some reason this code will not work (no errors). I've rtm and I haven't found anything combining fetch_assoc with prepared statements, so I'm not sure if it's even possible. Any help to get this working is appreciated, here's my code currently.
$where = $_GET['section'];
$mysqli = mysqli_connect("localhost", "root", "","test");
if($stmt = mysqli_prepare($mysqli,"SELECT title, img, active, price FROM ? ORDER by ID limit 5 ")){
mysqli_stmt_bind_param($stmt, 's', $where);
mysqli_stmt_execute($mysqli);
mysqli_stmt_fetch($mysqli);
while($row = mysqli_fetch_assoc($stmt)){
if($row['active']=="yes"){
echo 'the rest of my stuff goes here';
From the PHP website page for mysqli->prepare (with emphasis added to the most relevant part):
Note:
The markers are legal only in certain places in SQL statements. For
example, they are allowed in the VALUES() list of an INSERT statement
(to specify column values for a row), or in a comparison with a column
in a WHERE clause to specify a comparison value.
However, they are not allowed for identifiers (such as table or column
names), in the select list that names the columns to be returned by a
SELECT statement), or to specify both operands of a binary operator
such as the = equal sign. The latter restriction is necessary because
it would be impossible to determine the parameter type. In general,
parameters are legal only in Data Manipulation Language (DML)
statements, and not in Data Definition Language (DDL) statements.
Assuming you can get past that problem, your use of mysqli is a little confused. You correctly bind your parameters and execute, but you've mixed up two different ways of getting at your results. Either
Use mysqli_stmt_get_result to fetch the result set and then use mysqli_fetch_assoc on that, or
Bind your results with mysqli_stmt_bind_result, and then use mysqli_stmt_fetch to fetch the next set of results into your bound variables. (Usually you'd iterate over the results using something like while(mysqli_stmt_fetch($stmt)){ //do stuff here }
Another way style, we can write it below:
$mysqli=new mysqli("host","user","pass","db");
$stmt = $mysqli->prepare($query);
$stmt->bind_param('s', $variable);
$stmt->execute();
$result = $stmt->get_result();
while($row = $result->fetch_assoc()){
....
}

Categories