How to use Functions to create Prepared Statements - php

I am new to these prepared statements (all my code so far has been procedural), and I was trying to create a function for executing prepared statements so I could save time writing a statement for every SQL query I need.
function executeQuery($stmt,$mysqli,$sql,$type,$param1,$param2,$param3){
$stmt = $mysqli -> stmt_init();
$stmt = $mysqli -> prepare($sql);
$stmt->bind_param($type,$param1,$param2,$param3);
$stmt->execute();
$stmt->close();
}
As you can see, my issue is that I would need a different function for prepared statements that only deal with 1 parameter in the query, one for 2 parameters, another for 3 and so on. I thought of making $param an array but I don't think that quite works.
Any ideas?

Related

PDO emulate off, binding same value multiple times

I have the following bit of code in PHP7. I'm using PDO to connect to MySQL.
With PDO prepared statements emulation on, this code works successful:
$query = $db_con->prepare('SELECT * FROM matches WHERE matches.home_team_id=:team_id OR matches.away_team_id=:team_id');
$query->bindValue(':team_id', $team_id, PDO::PARAM_STR);
$query->execute();
return $query->fetchAll();
But with true PDO prepared statements (emulation off), the previous code gives an error that not enough values were bound. I'm forced to do the following:
$query = $db_con->prepare('SELECT * FROM matches WHERE matches.home_team_id=:team_id OR matches.away_team_id=:team_id2');
$query->bindValue(':team_id', $team_id, PDO::PARAM_STR);
$query->bindValue(':team_id2', $team_id, PDO::PARAM_STR);
$query->execute();
return $query->fetchAll();
This works, but is there any way I don't have to declare the same variable twice with true prepared statements? I have a lot of these queries, and would like to replace them all to use true prepared statements.
As someone asked in the comments: why do I want emulation off? I didn't really have a preference, but now it seems that true prepared statements are more strict than emulated statements. Is my understanding correct that is is better to develop with true prepared statements to guarantee it will work with both settings?
There is a way by change the query
$query=$db_con->prepare('SELECT*FROM matches WHERE :team_id in(home_team_id,away_team_id)');
$query->bindValue(':team_id', $team_id, PDO::PARAM_STR);
$query->execute();
This may not desirable, but it declare variable at once for case.
Hope this helpful.
A simple solution is to use a counter. In that way you can keep emulation off and still bind the same value multiple times without the need to count how many times you've used it, or renumber when you change the query.
$count=0;
$query = $db_con->prepare(
'SELECT * FROM matches WHERE
matches.home_team_id=:team_id'.(++$count).' OR
matches.away_team_id=:team_id'.(++$count)
);
for($i=1; $i<($count+1) ;++$i){
$query->bindValue(':team_id'.$i, $team_id, PDO::PARAM_STR);
}
$query->execute();
return $query->fetchAll();

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.

How to run Transact-SQL with PHP PDO

I have a pl/sql script which is made up of multiple statments:
SET #sql = NULL;
**Select values into variable**;
**Build a statment**;
**Prepare and execute statment**;
Run directly from the my-sql database this ouputs a standard table of results.
But as I understand it, PDO has issues/limitations when it comes to running multiple statments and returns zero results for me,
what would be the best way to return this queries results as a normal result set?
My experience with PDO has been limited to standard querires so i appologise if this is the wrong approach.
First how you can pl-sql statements on MySQL DB ?
However If you have some MySQL statements, You can better create a MySQL Procedure and put code into that. Then call the procedure through PDO. Like following example from PDO Prepared Statments
$stmt = $dbh->prepare("CALL sp_returns_string(?)");
$stmt->bindParam(1, $return_value, PDO::PARAM_STR, 4000);
// call the stored procedure
$stmt->execute();

Mysqli prepared statement (SQL injection prevention)

after stopping the use of deprecated mysql_* functions, I switched to mysqli. But then, I noticed that non-prepared statements are non-secure against SQL injection. Then, I changed again my code.
What I had was the following function that checks if the variable $ID exists in the database and prints the value of title for that row:
function showPostTitle($ID, $mysqli) {
$result = $mysqli -> query("SELECT ID, title FROM blog where ID = $ID");
$row = $result -> fetch_array(MYSQLI_BOTH);
echo $row['title'];
}
I changed it to this:
function showPostTitle($ID, $mysqli) {
$stmt = $mysqli -> prepare("SELECT ID, title FROM blog WHERE ID = ?");
$stmt -> bind_param("i", $ID);
$stmt -> execute();
$stmt -> bind_result($ID, $title);
$stmt -> fetch();
print_r($title);
$stmt -> free_result();
}
My question is: is this the correct way to implement prepared statements? Plus, am I safe now from SQL Injections? Big thanks to whoever will answer this question :)
Your mysqli logic seems fine, there are some examples in the PHP manual here in case you have not seen them.
Why are you selecting the ID when not consuming it though? Also you don't really need to bind a result when it's only going to have one row returned in the full result set as I assume will happen in this case (ID is unique index in the table), use get_result instead.
Using mysqli prepare will protect against all the common injection attacks but not 0-day style stuff which hasn't made it to the driver yet.
Take a look at this post:
Are PDO prepared statements sufficient to prevent SQL injection?
It's using PDO instead of MySQLi, which is solving the same problem by creating prepared statements.
Sorry for not answering your question, but just wanted to provide a resource for you to consider.

multi query with prepared statements

I am trying understand how multi queries work in mysqli. But I confess that is not easy to understand.
Basically how I can do these queries in a multi query? The page doesn't talk about prepared statements in multi queries.
($sql = $db -> prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)"));
$sql -> bind_param('sss', $name, $email, $hash);
$sql -> execute();
($sq = $db -> prepare("INSERT INTO activation_link_password_reset (activation_link) VALUES (?)"));
$sq -> bind_param('s', $linkHash);
$sq -> execute();
You can't use prepared statements there, and the speedup is also negligible, so go for the easier to debug seperate queries.
If you really want to do it in 1 call with prepared statements, create a PROCEDURE (even more difficult to debug...), and prepare CALL(:param1,:param2);.
I actually just figured this out a few days ago. The move to MySQLi is not a trivial one but ill go ahead and show you the query loop for prepared statements.
$db = new mysqli(...)
$statement = $db->prepare('SELECT count(*) as [hitchhikers] FROM `T_Users` WHERE `id` > ? AND `signin` like ?');
$statement->bind_param("ss", 42, '%adams');
if ($statement->execute())
{
$statement->store_result();
$statement->bind_result($hitchhikers);
$statement->fetch();
// do something with hitchhikers here
}
else
{
// there was a problem with the execution, check $db->error
}
$statement->close();
$db->next_result();
Everything here works similar to the non oo format by replacing -> with _ and passing the returned value into the new function, but this process here is pretty much what you should look to be doing with each of those statements. You can abstract it away with a mysqli wrapper class as well.
After the $db->next_result() call you are able to repeat the process again. This change has to do with the way the MySQL connection and results are handled with MySQLi. You can, of course, avoid this issue entirely by switching back to mysql_ queries and resources.
Specifically for multi_query, you separate your queries with a semicolon, in a single string. The example you linked to shows how to process the results.
MySQLi Book #PHP.net

Categories