I am trying to store the id of a username which I got from $_SESSION to a variable but I can't get the SQL statement to work. The usernames are stored in a database called users and have an ID as primary key. Can someone tell me how I can correct this? Thanks
$name = $_SESSION['username']; //get username of user currently logged in
$rid = $db->exec("SELECT id FROM users WHERE username = '$name'");
From the PHP documentation on PDO::exec():
PDO::exec() does not return results from a SELECT statement. For a SELECT statement that you only need to issue once during your program, consider issuing PDO::query(). For a statement that you need to issue multiple times, prepare a PDOStatement object with PDO::prepare() and issue the statement with PDOStatement::execute().
This means that you cannot use exec() on a SELECT query - instead, you must use query() or prepare(). For any queries using variables or user-input, use prepare() and placeholders in the query for variables, like below, to protect your database against SQL-injection.
$stmt = $db->prepare("SELECT id FROM users WHERE username = :name");
$stmt->execute(["name" => $name]);
if ($row = $stmt->fetch()) {
// $row holds the id
} else {
// No rows were returned at all! No matches for $name
}
Now $row holds the id(s) if the query returned any result at all. Depending on your fetch-type, it might be $row['id'], $row[0], $row->id or a combination of these.
If you expect more than one result, you need to loop while ($row = $stmt->fetch()), or use $stmt->fetchAll();
http://php.net/manual/en/pdo.exec.php
How can I prevent SQL injection in PHP?
Related
I'm in the process of migrating from mySQL based php to PDO. I'm working an if statement. Basically, I want to query a value from the database and check if anything gets returned.
With mySQL I would have done this:
//Query the entered data to see if it matches
$myQuery = "SELECT * FROM $tbl_name WHERE myData ='$MyData'";
$myResult = mysql_query($myQuery);
// If statement
if( mysql_num_rows($myResult) >=1 ) {
$result .= "The data matched and SQL query was successful";
}
With PDO I have this so far, although it's not working yet:
//Query the entered data to see if it matches
$myQuery = "SELECT myData FROM table_name WHERE myData = '$myData'";
$myResult = $db->single($myQuery);
// If statement
if($myResult == 1) {
$result .= "The data matched and PDO query was successful";
}
Although, from what I've seen you don't need to separate the query and the result with PDO and could combine both the query and result into a single statement.
$myQuery = $db->prepare("SELECT myData FROM table_name WHERE myData = ?");
$myQuery->execute(array($myData));
$myResult->rowCount($myQuery);
// If statement
if($myResult == 1) {
$result .= "The data matched and SQL query was successful";
}
In PDO you would do it like this:
$data_exists = $dbh->prepare('SELECT 1
FROM `table_name`
WHERE `myData` = ?');
$data_exists->execute(array($myData));
if ($data_exists->rowCount() == 1) {
$result .= 'The data matched and PDO query was successful';
}
To answer your question you could use PDO's function rowCount().
if ($myResult->rowCount() > 0) {
$result .= 'The data matched and PDO query was successful';
}
But notice that your PDO query is not safe. It is still vulnerable for MySQL injection since you directly insert a variable into your query. Use PDO's function bindParam() or bindValue() instead.
Although, from what I've seen you don't need to separate the query and the result with PDO and could combine both the query and result into a single statement.
It does allow it the way you shouldn't use PDO anyway. but nevertheless, your single function is not PDO and I doubt it will allow you any num rows. But you don't need that number anyway.
So, to make things straight
Your single() function ought to have support for prepared statements.
Having result from this function, you need no num rows at all
Here it goes
public function single($myQuery, $params = NULL, $style = PDO::FETCH_ASSOC)
{
$stmt = $this->pdo->prepare($myQuery);
$stmt->execute($params);
return $stmt->fetch($style);
}
$myQuery = "SELECT myData FROM table_name WHERE myData = ?";
$myResult = $db->single($myQuery, [$myData]);
if($myResult) {
$result .= "The data matched and PDO query was successful";
}
if you don't need the result itself, then you can shorten a bit
$myQuery = "SELECT 1 FROM table_name WHERE myData = ?";
if($db->single($myQuery, [$myData])) {
$result .= "The data matched and PDO query was successful";
}
Ok. Thank you everyone for your answers. After taking them into consideration and doing some testing, I'd like share some findings with you.
In regards to issue at hand, which is setting up an if statement when checking database values with PDO I've noticed the a few differences. This may be obvious to some of you, but for someone coming from mysql (like me) it's not.
After doing some testing I found that I couldn't query a string with PDO as you would with mysql. Furthermore, in mysql you are able to set the string value prior to querying it in the database.
From what I can see, PDO will only query and return arrays. So you can't simply insert a string value and check for it.
In regards my question, I found that using that:
My querying PDO syntax was incorrect.
When it was correct, I was only able to query an array which returns an array.
Anyway this is what i did:
// Get's the entire column called "ColumnName"
$getColumn = $db->column("SELECT columName FROM table_name ");
// Check if the returned array contains a string.
$myString = "matchThisString";
if (in_array($myString, $getColumn)) {
echo "A Match was found";
}
else {
echo "No match was found";
}
I would recommend reading the following:
http://www.php.net/manual/en/pdostatement.fetch.php
http://www.php.net/manual/en/language.types.boolean.php
http://www.php.net/manual/en/language.types.array.php
All answers suggesting to use rowCount() are wrong, rowCount() returns a non zero value only in operations that Affect rows, not selected rows, or at least as sated in PHP manual: PDO::Statement it's not guarantied.
PDOStatement::rowCount() returns the number of rows
affected by
the last DELETE, INSERT, or UPDATE statement executed by the corresponding
PDOStatement object.
If the last SQL statement executed by the associated PDOStatement was a SELECT
statement, some databases may return the number of rows returned by that statement.
However, this behaviour is not guaranteed for all databases and should not be
relied on for portable applications.
More Text From The Manual
Example #2 Counting rows returned by a SELECT statement
For most databases, PDOStatement::rowCount() does not return the
number of rows affected by a SELECT statement. Instead, use
PDO::query() to issue a SELECT COUNT(*) statement with the same
predicates as your intended SELECT statement, then use
PDOStatement::fetchColumn() to retrieve the number of rows that
will be returned. Your application can then perform the correct
action.
At least I know that I had tons of problems with it.
One other way is to use:
$rows = stmt->fetchAll(PDO::FETCH_ASSOC);
if (count($rows))
{
//Do something here
}
else
{
//Do something else here.
}
The above chunk of code is good if you expect small data sets returned. If we're talking about huge data sets, then you're better of executing 2 queries, one with a COUNT in it with the same conditions as your select statement and then the SELECT statement like this:
$sql = "SELECT COUNT(*) FROM $tbl_name WHERE myData ='$MyData";
$count = $db->query($sql)->fetch();
if ($count[0] > 0)
{
$myQuery = "SELECT * FROM $tbl_name WHERE myData ='$MyData'";
//.... Continue your code here since now you know for sure that your
//query will return rows....
//.....
}
else
{
//handle the case that no data were returned.
}
The code chunks above are just for demonstration, so you can understand what and how to do.
I can't guarantee that this is the best way to do it, it's just the way I do it. Cheers.
Also a better way to do your thing is to use Prepared Statements as someone or some suggested. That has nothing to do with the way you're gonna deal with your problem here, it's just a safer practice in general since prepared statements prevent SQL Injection if not completely then to a really good degree (not sure about it).
You can do something like this :
$sql = "SELECT * FROM animals";
$stmt = $dbh->query($sql);
$result_count = $stmt->fetch(PDO::FETCH_ASSOC);
if($result_count == 1)
{
$result .= "The data matched and PDO query was successful";
}
In MySQL, how can I select the data of one column, only for the rows where the value of the same row, in another column, is session_id (I want all the values, not only the first one)
I have tried this:
SELECT column_name FROM table_name WHERE ID = $session_id
...but it dosen't work. It only selects the first row.
edit, the code I'm using.
<?php
$dn = mysql_query("SELECT IDcontact FROM contacts WHERE ID = '".$_SESSION['id']."'");
if(mysql_num_rows($dn)>0)
{
$dnn = mysql_fetch_array($dn);
$req = mysql_query("select TitreEvent, DescriptionEvent, MomentEvent, image_small from users_event where Confidentialite = 'Public' and ID = " . $dnn['IDcontact']);
while($dnn = mysql_fetch_array($req))
{
?>
So it takes for exemple, the value of the contact/friend (IDcontact), form the database «contacts», where the ID of the logged user is. What I want is to output the event of all the IDcontact, cause actually, it only output the event of the most recent friend added, witch is... the first row of the «contacts» database.
The mysql_fetch_array() function returns only one row from the query's result set. If you want to get all the rows produced by the query, you have to call it in a loop:
while ($row = mysql_fetch_array($dn)) {
// Do stuff with $row...
}
Also, this function is deprecated. You should instead be using either mysqli or PDO to run your queries. See the PHP documentation on choosing an API for more information.
Since you edited your question to show that you're running a second query based on the results of the first one, note that you can do both the IDcontact lookup and get the users_event info in a single query by joining the two tables:
select TitreEvent, DescriptionEvent, MomentEvent, image_small
from users_event
join contacts
on contacts.IDcontact = users_event.ID
where contacts.ID = $session_id
Last but not least, anytime you insert variables (such as your session_id) into a database query, you need to be mindful of SQL injection. If the session ID comes from a parameter that the user can control (e.g. a browser cookie), an attacker could send a malicious session ID that contains SQL code to run arbitrary queries in your database. For safety, you should first create a prepared statement that has a placeholder where the parameter should go:
... where contacts.ID = ?
and then plug in the session_id variable afterward as a "bind parameter". Both mysqli and PDO provide ways to do this: mysqli_stmt_bind_param and PDOStatement::bindParam.
I've been looking up around for a couple tutorials of this and I've seemed out of luck. Basically, I have a database containing a winner's user ID (corresponding to the winners user ID) and a loser's ID. I am trying to create a members profile where it counts up all the rows the member has won. Here is what I have came up with:
$web = mysqli_query("select SUM(matches) WHERE WinnerUID='".$req_user_info['id']."'");
$web_sum=mysqli_fetch_assoc($web);
echo $web_sum;
Unfortunately, it doesn't display any number. Can anyone help?
I think you're looking for COUNT() not SUM(). And you didn't include a table name. Also remember that mysqli_fetch_assoc() returns the row as an array, it doesn't return the first column's value. Also, mysqli_query() requires the connection as the first argument.
$web = mysqli_query($conn, "select COUNT(*) as total FROM matches WHERE WinnerUID='".(int)$req_user_info['id']."'");
$row = mysqli_fetch_assoc($web);
echo $row['total'];
Don't concatenate variables into your SQL. Use a Prepared Statement with bound parameters. I have casted your ID as an (int) in the above code, which is a quick fix but you should switch to a Prepared Statement.
Prepared Statement example (object oriented interface instead of procedural):
if ($stmt = $conn->prepare("select COUNT(*) from matches WHERE WinnerUID = ?")) {
$stmt->bind_param("i", $req_user_info['id']);
$stmt->execute();
$stmt->bind_result($web_sum);
$stmt->fetch();
echo $web_sum;
$stmt->close();
}
I am trying to understand this SQL statements :
$id = 5;
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
$stmt->execute(array('id' => $id));
while($row = $stmt->fetch()) {
print_r($row);
}
Can someone please explain me step by step what exactly is going on here?
From what i understand :
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
1) $stmt is about to take as iinput an SQL query. The SQL query is to select all the rows from a table that their id is equal to 5.
$stmt->execute(array('id' => $id));
2) We execute the statement. Now the $stmt has these rows?
$row = $stmt->fetch()
3) This is the most confusing line for me. What exactly happens here? Variable "row" takes one by one the rows that have id = 5 ? Is that what fetch() does ? And if yes , how exaxtly does it return the results? Its an array of all the correct answers? EG all the rows that have id = 5 ? I dont understand how exactly this while loop works here.The first time it runs "row" will have the first row ? The second time it runs , will have the second row that satisfies our creteria (id = 5) and so on? Is it like that every time i run fetch one result will be returned? And next time i run fetch , the next result , till there is no more result to satisfy the query?
I thing i am so close to get this one. Anything that could help me understand it completely would be highly appreciated !
I'll explain as comments:
$id = 5;
// Create a prepared statement - don't actually execute the statement yet.
// The :id value in the statement will be replaced by a parameter value (safely) when the
// statement is executed
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
// Execute the statement against the DB - the $stmt var now contains the result set for the
// executed statement. e.g. it contains *all* the results that the query fetched
$stmt->execute(array('id' => $id));
// Now we loop through the rows in the result set (they are all in memory at this point).
// "fetch" will start from row 1 and return the next result each time you call it again.
// when there are no more rows it returns FALSE and therefore breaks out of the while loop
while($row = $stmt->fetch()) {
print_r($row);
}
Just checking docs also and whilst this is how it was done previously (been years since I've touched PHP) it looks like stmt->fetch() actually places results into bound variables:
http://php.net/manual/en/mysqli-stmt.fetch.php
$row = array();
stmt_bind_assoc($stmt, $row);
// loop through all result rows
while ($stmt->fetch())
{
print_r($row);
}
Does the code you originally posted actually work? It doesn't appear you bind any variables and therefore since the $stmt-fetch() call returns bool TRUE/FALSE it would seem to be that $row would not get set to anything but TRUE/FALSE
here it uses PDO for execution,
Repeated SELECT using prepared statements through which you can call repeated query
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
it defines the prepared statement where :id is placeholder
$stmt->execute(array('id' => $id));
this places assigns the value to placeholder and execute the query
$row = $stmt->fetch()
it fetch the record from select
for more reference visit the link
http://www.php.net/manual/en/pdo.prepared-statements.php
I'm trying to count all of the rows from an item list where the id matches a user input. I am switching all of my code from mysql to PDO as I have learned it is much better.
The code below is what I found to work in my situation.
$id = '0';
$sql="SELECT count(*) FROM item_list WHERE item_id = $id";
$data=$connMembers->query($sql)->fetchcolumn();
echo $data;
However, It is not safe for a live site due to sql injections.
I want to know how can I change it to work whare it sanatizes the user input.
I would prefer using a prepare and execute functions so the variables are kept seperately.
So is there something I can do?
This is where you start binding parameters. I prefer to do it using ? and one array for inputs.
Assuming $connMembers is your PDO object:
$sql="SELECT COUNT(*) FROM item_list WHERE item_id = ?";
$input=array($id); //Input for execute should always be an array
$statement=$connMembers->prepare($sql);
$statement->execute($input);
$data=$statement->fetchObject();
var_dump($data);
To add more variables to your sql, just add another ? to the query and add the variable to your input.
$sql="SELECT COUNT(*) FROM item_list WHERE item_id = ? AND item_name=?";
$input=array($id, $name); //Input for execute should always be an array
$statement=$connMembers->prepare($sql);
$statement->execute($input);
$data=$statement->fetchObject();
var_dump($data);
OR you can use bindParam:
$sql="SELECT COUNT(*) FROM item_list WHERE item_id = :itemID";
$statement=$connMembers->prepare($sql);
$statement->bindParam(':itemID', $id);
/*Here I am binding parameters instead of passing
an array parameter to the execute() */
$statement->execute();
$data=$statement->fetchObject();
var_dump($data);