PDO Database access WHERE title = $title - php

I'm trying to learn to use PDO instead of MySQLi for database access and I'm having trouble selecting data from the database. I want to use:
$STH = $DBH->query('SELECT * FROM ratings WHERE title=$title ORDER BY date ASC');
$STH->setFetchMode(PDO::FETCH_ASSOC);
while($row = $STH->fetch()) {
echo $row['title'];
}
but I'm getting this error:
Fatal error: Call to a member function setFetchMode() on a
non-object in
/home/owencont/public_html/owenstest.com/ratemystudents/index.php
on line 6
If I take out the WHERE statement it works fine. How can I select a row based on if it's value matches a variable?
Thanks,
Owen

It's likely a SQL syntax error, because you forgot to quote $title. It ended up as bareword in the query (also not even interpolated as string), resulting in an error. And your PDO connection was not configured to report errors. Use ->quote() on arguments before the ->query():
$title = $DBH->quote($title);
$STH = $DBH->query("SELECT * FROM ratings WHERE title=$title ");
Or better yet, use parameterized SQL:
$STH = $DBH->prepare("SELECT * FROM ratings WHERE title=? ");
$STH->execute(array($title));

Take a look at PDO::prepare and PDOStatement::execute. The safest way to add user content to a query is to prepare a basic statement and bind the parameter to it. Example (note the question mark in the SQL statement):
$STH = $DBH->query('SELECT * FROM ratings WHERE title=? ORDER BY date ASC');
$STH->execute( array( $title ) );
while( $row = $STH->fetch( PDO::FETCH_ASSOC ) );

Make PDO throw errors so you can see what exactly goes wrong. See How to squeeze error message out of PDO?
You are probably missing quotes around $title but this scenario really calls for prepared statements instead.

remove the variable out of the sql statement because its a php variable
$STH = $DBH->query('SELECT * FROM ratings WHERE title=' . $title . 'ORDER BY date ASC');

Use double quotes instead of single quotes as a parameter of the query-method.
The reason you're getting this error is because the query-method fails and so the $STH object isn't created. You should implement some error handling.

Related

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.

Placing a variable into a PDO Statement

is it possible to create a pdo query with a variable? Example:
$q = "SELECT COUNT (*) c FROM blogpages WHERE keywords LIKE '%test%' ";
then
$query = $db->query("$q");
$result = $query->fetch(PDO::FETCH_ASSOC);
when i do this i get an error
"Call to a member function fetch() on a non-object in C....."
i want to know is there a way to place the query in there as a variable because the query changes depending on how many OR statements are in the query
query()
PDO::query — Executes an SQL statement, returning a result set as a
PDOStatement object
And problem in your query with space between count and (*)
SELECT COUNT (*)..
^^
SO no need to fetch data just use
$q = "SELECT COUNT(*) c FROM blogpages WHERE keywords LIKE '%test%' ";
foreach ($db->query($q) as $row) {
print $row['c'] . "\t";
}

PDO query not displaying results?

Okay so i am new to PDO statements so i am unsure if i have done a syntax error or whatnot. The php file does not show any errors:
<?php
include('db_config.php');
$itemName = 'Item1';
$sql = "SELECT * FROM order WHERE itemName = $itemName;";
$stmt = $conn->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
echo $row['itemName'];
}
?>
My objective is to pull an item using bootstraps datepicker, but for the purpose of this testing i am using the itemName.
The php file comes up blank?
I have checked the field names, db_config, and am unsure where the issue is coming from.
Please let me know if i have done an error in my statement or anything that seems wrong.
Firstly, you're using a MySQL reserved word, being order and it requires special attention; mainly using ticks around it.
Then since we're dealing with a string, $itemName needs to be wrapped in quotes.
<?php
include('db_config.php');
$itemName = 'Item1';
$sql = "SELECT * FROM `order` WHERE itemName = '$itemName';";
$stmt = $conn->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
echo $row['itemName'];
}
?>
Either use ticks around your table name, or rename it to "orders", it's not a reserved keyword.
"The php file does not show any errors:"
That's because you're not checking for them.
Add $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); right after the connection is opened.
Now, if you're going to use PDO, use PDO with prepared statements, they're much safer.
As per a comment you left under your question containing the MySQL error:
1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'order
Read it near 'order it starts at "order".
Now, if ever your query should ever contain any character that MySQL will complain about, such as a quote etc. then you will need to escape your query and use prepared statements.
For example, if using:
$itemName = "Timmy's Sour Dough";
would translate to
WHERE itemName = 'Timmy's Sour Dough'
in turn throwing a syntax error.
So, it's best to immediately escape any data right away.
Edit
Your use of prepare and new to PDO collectively suggest that you are already trying to use prepared statements, just not the right way. You're just a little off from a well prepared statement. One correct way in your code would be
$sql = "SELECT * FROM `order` WHERE itemName = ? ";
$stmt = $conn->prepare($sql);
$stmt->execute(array($itemName));
Notice how we have a ? in your query then we are sending a value for it in your execute call. There you go :)
Using PDO with prepared statements will take care of that.
You're completely ignoring the main reason people use PDO. Prepared statements are what you should be using, which would make your query look like this:
$itemName = 'Item1';
$sql = "SELECT * FROM order WHERE itemName = ?";
$stmt = $conn->prepare($sql);
$stmt->bindParam(1, $item, PDO::PARAM_STR);
$stmt->execute();
Read up on bindParam().
In future, turn on your error reporting at the beginning of the script with this:
ini_set('display_errors', 1);
error_reporting(E_ALL);
That will save you a lot of time.
Looks like there is an error in you sql statement. since itemName is either a varchar or text in your database, you need to put it in single quotes in the query:
$sql = "SELECT * FROM order WHERE itemName = '$itemName';";

How to make a select statement PDO and end up with $row['field']

I want to make a php PDO select statement and end up with the possibility to place $row['field'] wherever I want.
In normal mysql I would have done as following:
$row = mysql_fetch_array(mysql_query("SELECT * FROM table WHERE id = '1234'"));
And then I would be able to place $row['name'] in one place and $row['items'] in another.
How to do this?
$sth = $dbh->prepare("SELECT * FROM table WHERE id = '1234'");
$sth->execute();
$row = $sth->fetch(PDO::FETCH_ASSOC);
echo $row['field'];
The PDO counterpart to mysql_fetch_array is fetch(PDO::FETCH_BOTH). If you only care about an associative array, you can use fetch(PDO::FETCH_ASSOC)
I suggest you read up this short tutorial that will get you up and running with PDO rather quickly: http://net.tutsplus.com/tutorials/php/why-you-should-be-using-phps-pdo-for-database-access/

PHP prepared statement within a prepared statement

I'm going through a video tutorial about doing a menu using a db. Instead of doing it with procedural PHP like in the video, I tried doing it with prepared statements OOP style. It doesn't work and I can't figure out why.
It runs fine until line 17, where it dies with this error:
Fatal error: Call to a member function bind_param() on a non-object in C:\wamp\www\widget_corp\content.php on line 17
And here's the code:
<?php
$query = $connection->prepare('SELECT menu_name, id FROM subjects ORDER BY position ASC;');
$query->execute();
$query->bind_result($menu_name, $sid);
while ($query->fetch()){
echo "<li>{$menu_name} {$sid}</li>";
$query2 = $connection->prepare('SELECT menu_name FROM pages WHERE subject_id = ? ORDER BY position ASC;');
$query2->bind_param("i", $sid); //This is line 17
$query2->execute();
$query2->bind_result($menu_name);
echo "<ul class='pages'>";
while ($query2->fetch()){
echo "<li>{$menu_name}</li>";
}
echo "</ul>";
}
$query->close();
?>
Is it impossible to do a prepared statement within stmt->fetch();?
Figured it out:
After executing and binding the result, it has to be stored (if another prepared statement is to be put in the fetch). So the fetching in this case has to be read from a buffered result.
In other words, can't execute another query until a fetch on the same connection is in progress.
The working code:
$query = $connection->prepare("SELECT menu_name, id FROM subjects ORDER BY position ASC;");
$query->execute();
$query->bind_result($menu_name, $sid);
$query->store_result();
$stmt = mysqli_prepare($con,"SELECT menu_name, id FROM subjects ORDER BY position ASC");
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $menu_name, $id);
while (mysqli_stmt_fetch($stmt))
{
$stmt2 = mysqli_prepare($con2,"SELECT menu_name FROM pages WHERE subject_id = ? ORDER BY position ASC;");
mysqli_stmt_bind_param($stmt2,$id);
mysqli_stmt_execute($stmt2);
mysqli_stmt_bind_result($stmt2, $name);
while (mysqli_stmt_fetch($stmt2))
echo $name;
}
look at the $con and $con2, you can not execute a prepare statement within another ps using the same connection !!!
Yes, you can have several prepared statements : one of the ideas of prepared statements is "prepare once, execute several times".
So, you should prepare the statement outside of the loop -- so it's prepared only once
And execute it, several times, insidde the loop.
The Fatal error you get means that $query2 on line 17, is not an object -- which means the prepare failed.
A prepare typically fails when there is an error in it ; are you sure your query is valid ? The tables and columns names are OK ?
You should be able to get an error message, when the prepare fails, using mysqli->error() -- or PDO::errorInfo()
You don't say what DB extension you are using but you don't seem to test the return value of any function you are using. You can't assume that DB calls will always run flawlessly.

Categories