PDO: When to use bindParam, execute(array)) and PDO::FETCH_ASSOC? - php

I'm new to PDO, in fact, this is the first time that I'm using it. All the while I've been using mysql which is depreciated. And so recently, I'm trying to update all my site to use PDO which is better and safer according to many sources that I found from the internet.
However, those tutorials is making me even more curious and full of questions. I've been google for the whole day and I still can't get the best answer or examples.
Let's start by this code below,
// query
$sql = "SELECT title FROM books ORDER BY title";
$q = $conn->query($sql);
$q->setFetchMode(PDO::FETCH_ASSOC);
// fetch
while($r = $q->fetch()){
print_r($r);
}
I do understand that it fetches the data just like mysql_fetch_assoc. But, here's another code that I found from the net.
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
$stmt->execute(array('name' => $name));
foreach ($stmt as $row) {
// do something with $row
}
and lastly, this:
$stm = $pdo->prepare('SELECT * FROM table LIMIT ?, ?');
$stm->bindParam(1, $limit_from,PDO::PARAM_INT);
$stm->bindParam(2, $per_page,PDO::PARAM_INT);
$stm->execute();
$data = $stm->fetchAll();
Why are there so many different methods to fetch a data ?
I somehow found out that with bindParam, you're able to set integer or strings for the variable? But with this below...
$pdo->execute(array(':col2' => $col2, ':col3' => $col3, ':col4' => $col4));
Am I still able to mix integer and strings without declaring if it's integer or strings?
Is it ok if I do like this ? mixing strings and integer in execute array...
$sql = "INSERT INTO books (id,author) VALUES (:id,:author)";
$q = $conn->prepare($sql);
$q->execute(array(':author'=>'string', ':id'=>1));
And also, does all codes above avoid SQL injection ?
I somehow prefer the execute array method as it is shorter and I don't want to declare if it's integer or strings every time like using the bindParam method.

Related

How to return a PDO result with prepared statements and parameterized queries to a webpage?

I used the following answer in order to patch SQLi(How can I prevent SQL injection in PHP?), however, although the connection to the database is made, the pages are left blank, as if the data is not returned. Here's an example:
public function getPlayerInfo($name){
$stmt = $this->db->prepare("SELECT * FROM playerinfo WHERE PlayerName = ':name'");
//$stmt->execute();
return $stmt->execute(array('name' => $name)); } // I tried using this but it didnt work, information page is left blank
return $stmt->fetchAll(PDO::FETCH_ASSOC); } // This one used to work before I applied the patch
I'm using the function in the player information page to display his information. How can I use it in order to return an array that can be read on that page via foreach?
Thanks!
Remove single quotes around the placeholder :name, your prepared statement should be like this:
$stmt = $this->db->prepare("SELECT * FROM playerinfo WHERE PlayerName = :name");
Here's the complete getPlayerInfo() method,
public function getPlayerInfo($name){
$stmt = $this->db->prepare("SELECT * FROM playerinfo WHERE PlayerName = :name");
$stmt->execute(array('name' => $name));
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
This issue has already been documented here, http://php.net/manual/en/pdo.prepare.php#111458

Using PHP variable in SQL query

I'm having some trouble using a variable declared in PHP with an SQL query. I have used the resources at How to include a PHP variable inside a MySQL insert statement but have had no luck with them. I realize this is prone to SQL injection and if someone wants to show me how to protect against that, I will gladly implement that. (I think by using mysql_real_escape_string but that may be deprecated?)
<?php
$q = 'Hospital_Name';
$query = "SELECT * FROM database.table WHERE field_name = 'hospital_name' AND value = '$q'";
$query_result = mysqli_query($conn, $query);
while ($row = mysqli_fetch_assoc($query_result)) {
echo $row['value'];
}
?>
I have tried switching '$q' with $q and that doesn't work. If I substitute the hospital name directly into the query, the SQL query and PHP output code works so I know that's not the problem unless for some reason it uses different logic with a variable when connecting to the database and executing the query.
Thank you in advance.
Edit: I'll go ahead and post more of my actual code instead of just the problem areas since unfortunately none of the answers provided have worked. I am trying to print out a "Case ID" that is the primary key tied to a patient. I am using a REDCap clinical database and their table structure is a little different than normal relational databases. My code is as follows:
<?php
$q = 'Hospital_Name';
$query = "SELECT * FROM database.table WHERE field_name = 'case_id' AND record in (SELECT distinct record FROM database.table WHERE field_name = 'hospital_name' AND value = '$q')";
$query_result = mysqli_query($conn, $query);
while ($row = mysqli_fetch_assoc($query_result)) {
echo $row['value'];
}
?>
I have tried substituting $q with '$q' and '".$q."' and none of those print out the case_id that I need. I also tried using the mysqli_stmt_* functions but they printed nothing but blank as well. Our server uses PHP version 5.3.3 if that is helpful.
Thanks again.
Do it like so
<?php
$q = 'mercy_west';
$query = "SELECT col1,col2,col3,col4 FROM database.table WHERE field_name = 'hospital_name' AND value = ?";
if($stmt = $db->query($query)){
$stmt->bind_param("s",$q); // s is for string, i for integer, number of these must match your ? marks in query. Then variable you're binding is the $q, Must match number of ? as well
$stmt->execute();
$stmt->bind_result($col1,$col2,$col3,$col4); // Can initialize these above with $col1 = "", but these bind what you're selecting. If you select 5 times, must have 5 variables, and they go in in order. select id,name, bind_result($id,name)
$stmt->store_result();
while($stmt->fetch()){ // fetch the results
echo $col1;
}
$stmt->close();
}
?>
Yes mysql_real_escape_string() is deprecated.
One solution, as hinted by answers like this one in that post you included a link to, is to use prepared statements. MySQLi and PDO both support binding parameters with prepared statements.
To continue using the mysqli_* functions, use:
mysqli_prepare() to get a prepared statement
mysqli_stmt_bind_param() to bind the parameter (e.g. for the WHERE condition value='$q')
mysqli_stmt_execute() to execute the statement
mysqli_stmt_bind_result() to send the output to a variable.
<?php
$q = 'Hospital_Name';
$query = "SELECT value FROM database.table WHERE field_name = 'hospital_name' AND value = ?";
$statement = mysqli_prepare($conn, $query);
//Bind parameter for $q; substituted for first ? in $query
//first parameter: 's' -> string
mysqli_stmt_bind_param($statement, 's', $q);
//execute the statement
mysqli_stmt_execute($statement);
//bind an output variable
mysqli_stmt_bind_result($stmt, $value);
while ( mysqli_stmt_fetch($stmt)) {
echo $value; //print the value from each returned row
}
If you consider using PDO, look at bindparam(). You will need to determine the parameters for the PDO constructor but then can use it to get prepared statements with the prepare() method.

PDO execute with array returns null

I'm trying to use good PDO as always and almost everything works but one query:
$primary = 'my_id';
$table = 'my_table';
// This or...
$statement = $this->conn->prepare("SELECT MAX(:id) AS id FROM :table");
$statement->bindParam(':id', $primary, PDO::PARAM_STR);
$statement->bindParam(':table', $table, PDO::PARAM_STR);
$statement->setFetchMode(PDO::FETCH_ASSOC);
$statement->execute();
// This one. Both doesn't work.
$statement = $this->conn->prepare("SELECT MAX(:id) AS id FROM :table");
$statement->setFetchMode(PDO::FETCH_ASSOC);
$arr = array(
':id' => 'my_id',
':table' => 'my_table',
);
$statement->execute($arr);
These just return a null array. I feel so confused. So I have tried that:
$statement = $this->conn->prepare("SELECT MAX(".$primary.") AS id FROM ".$table);
$statement->setFetchMode(PDO::FETCH_ASSOC);
$statement->execute();
And it works. I feel like I'm missing something but can't figure it out. So clearly there's a problem with binding I tried different variations such as writing one of the variable manually, but no luck so far.
Thanks in advance for any help...
You can't use parameters as table names in PDO, so you will have to change this to avoid that. This is not a limitation of PDO, but a limitation of MySQL directly. The manual states that
Parameter markers can be used only where data values should appear,
not for SQL keywords, identifiers, and so forth.
Table and column names are identifiers, so using placeholders for them is not supported. See this question for an alternative method.

Mysqli_fetch_assoc with params instead

I'm trying to patch over to params from standard mysqli. I canĀ“t wrap my head around how to target the columns i want with the new way to get results from db. lets say i have table with id, firstname, lastname, and about.
$query = mysqli_query($con, $sqlstmt);
while($row = mysqli_fetch_assoc($query){
$row['firstname'];
$row['about'];
}
this is easily done however when i try to use params,execute etc i cant really wrap it.
$stmt = mysqli_prepare($connect, "SELECT * FROM medlemmar WHERE firstname=?");
mysqli_stmt_bind_param($stmt, 's', $firstname,);
mysqli_stmt_execute($stmt);
I don't know how to fetch results from specific columns when using second choice and how to make an array of it etc.
In normal case i would just do
$array[]= $row['firstname']
When you use prepared statements, it takes one extra step to get the mysqli_result resource from the statement. Then you can use it like you used the mysqli_result you got from mysqli_query().
$stmt = $mysqli->prepare("SELECT name, userid FROM somewhere");
$stmt->execute();
$result = $stmt->get_result();
while($row = $result->fetch_assoc()) {
$row['firstname'];
$row['about'];
}
This usage requires mysqlnd, which is enabled by default in PHP 5.4+.
If you don't have mysqlnd, you have to bind results, like shown in the answer from #joaofgf.
It's worthwhile to upgrade to mysqlnd for its extra features and better performance.
you should use the associative bind stmt_bind_assoc()
example:
$stmt = $mysqli->prepare("SELECT name, userid FROM somewhere");
$stmt->execute();
$row = array();
stmt_bind_assoc($stmt, $row);
// loop through all result rows
while ($stmt->fetch()) {
print_r($row);
}
source: http://www.php.net/manual/en/mysqli-stmt.fetch.php

Writing this MySQLi query as a prepared statement

I have an existing MySQLi query:
$conn = dbConnect('query');
$galNumb = "SELECT COUNT(pj_gallery_id) FROM pj_galleries WHERE project = {$project}";
$gNumb = $conn->query($galNumb);
$row = $gNumb->fetch_row();
$galTotal = $row[0];
This counts the number of galleries per project that match the value in the query string contained in $project.
It works perfect but is not secure compared to a prepared statement. I have been researching this for two days and can not learn how to write this statement as a prepared statement. Any and all help will be insanely appreciated.
UPDATE:
I am flying by the seat of my pants here. I simply need to be shown how to code the above as a prepared statement. This sort of thing isn't resonating with my brain like learning PHP did and I'm just not getting any of this. The PHP manual is confusing and seems to be written for people who already understand PHP.
In short, I need a prepared statement version of the above code so that I can echo the result on the page. Currently, with what is in my DB, the number should be 3, and it consistently returns 1.
I wish I knew more so that I could better phrase my questions, but alas, I'm still learning. My apologies.
UPDATE 2:
Based on suggestions and research, I have this query written, but it ALWAYS returns the value 1, regardless of what's actually in the database:
$galNumb = "SELECT COUNT(pj_gallery_id) FROM pj_galleries WHERE project_part = ?";
$stmt = $conn->prepare($galNumb);
$stmt->bind_param('i', $project);
$gNumb = $stmt->execute();
Again, All I want to do is COUNT how many galleries are in each project. I know this should be simple but it isn't for me. There is currently 1 project in the DB with 3 galleries. The query should return 3.
This is as simple as it gets. This will prepare a sql statement, execute it and fetch the first row.
<?php
// create the prepared statement
$stmt = $conn->prepare('SELECT COUNT(pj_gallery_id) FROM pj_galleries WHERE project = ?');
// bind a variable to the statment
// the character denotes the type of the variable
// 's' for string
// 'i' for integer
$stmt->bind_param('i', $project);
// execute the query
$stmt->execute();
// get the result variable
$result = $stmt->get_result();
// fetch the row
$row = $result->fetch_row();
if ($row) {
echo "The count is " . $row[0];
}
?>
The documentation is pretty straightforward. You have a code example at the bottom.
http://php.net/manual/en/mysqli.prepare.php
$stmt = $dbConnection->prepare('SELECT COUNT(pj_gallery_id) FROM pj_galleries WHERE project = ?');
$stmt->bind_param('s', $project);
$stmt->execute();

Categories