Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Function
public function isUsernameAvailable($username) {
$sql = "SELECT COUNT(*) FROM users WHERE username = '$username'";
$sql = $this->db->quote($sql);
if ($sth = $this->db->query($sql)) {
if ($sth->fetchColumn() > 0) {
return false;
} else {
return true;
}
}
}
if (!$user->isUsernameAvailable($_POST['username'])) {
echo 'The username is already taken!';
$error = 1;
}
I get the output "The username is already taken!" even though It isn't.
select count(*)... will ALWAYS return a record, even nothing is matched
so, you can try this :
select 1 from ...;
between, a proper method to check any record return should be using rowCount
as indicate by the rest :-
you should make use of bind rather than using quote
function should always return a value
Your isUsernameAvailable function will return NULL (equals to FALSE) when the query fails. This will trigger the The username is already taken! message.
Looks like your SQL query always fails, which I think is no wonder because you blindly apply quotes onto it.
After running a SQL query, you must more properly deal with the case that the query failed, e.g. display that an internal SQL error occured and log it, so you can look into the log and locate the cause of the error.
Additionally, you should use the PDO more properly, specifically when you want to prevent SQL injection (which you must care about). See Best way to stop SQL Injection in PHP.
Use rowCount() instead of fetchColumn()
if ($sth->rowCount() > 0) {
fetchColumn returns false if there is no column and also see ajreal answer.
if ($sth = $this->db->query($sql)) {
if ($sth->fetchColumn() == false) {
return true;
} else {
return false;
}
}
Can you try using the following code?
$st->rowCount() > 0
$sql = "SELECT COUNT(*) FROM users WHERE username = '$username'";
$sql = $this->db->quote($sql);
You are quoting the whole query, this does not make any sense and is outright dangerous from a security standpoint – and probably results in an invalid query anyway.
Here's a more proper code:
// return TRUE if user is available
public function isUsernameAvailable($username) {
$sql = "SELECT id FROM users WHERE username = :username";
$stmt = $this->db->prepare($sql);
$stmt->execute(array(':username' => $username));
return $stmt->fetch() === FALSE;
}
if (!$user->isUsernameAvailable($_POST['username'])) {
echo 'The username is already taken!';
$error = 1;
}
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I am trying to select a value from the database. The select query is returning a 1 or 0. I want to echo 'yes' if the returned value is 1 and echo 'no' if the returned value is 0.
When I run the script I always get 'Yes'.
Does someone know what is wrong with my script?
Here is my PHP script:
$sql = "SELECT row FROM table WHERE id='". $_GET['id'] ."'";
$result = $conn->query($sql);
if ($result == 1){
echo 'yes';
}
else
{
echo 'No';
}
$conn->close();
For the answer it is important to know which Database API you use.
For most APIs
$result
will be a kind of result object which represents your result. Normally a collections of rows. You can call some kind of fetch function to get a row from a result, and then you would check whether this row contains 1 or 0.
You should read the documentation of your API for more details.
PHP gives always Yes, because the == Operator tries to do type conversion, and I suppose it converts both values to true.
http://php.net/manual/de/language.types.type-juggling.php
If you just want to know if the id exists, you can use a COUNT(*) expression. That way the query will be guaranteed to return exactly one row, whether the count is 0 or 1.
You should get into the habit of using parameters instead of creating SQL injection vulnerabilities by concatenating $_GET variables into your query.
And check for errors after every database function that may return an error.
$sql = "SELECT COUNT(*) FROM table WHERE id=?";
if (($stmt = $conn->prepare($sql) === false) {
error_log($conn->error);
die("Database error");
}
// assuming mysqli, but if you use PDO, binding is done differently
if ($stmt->bind_param('i', $_GET['id']) === false) {
error_log($stmt->error);
die("Database error");
}
if ($stmt->execute() === false) {
error_log($stmt->error);
die("Database error");
}
if (($result = $stmt->get_result()) === false) {
error_log($stmt->error);
die("Database error");
}
$row = $result->fetch_row();
$count = $row[0];
if ($count >= 1){
echo 'yes';
}
else
{
echo 'No';
}
$stmt->close();
$conn->close();
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I have a mySQLi prepared statement and a function I want to pass it to to check to see if the input meets the right format before executing it. I have determined in my actual code that if I move the $stmt->execute() statement just outside of the function that it works, but inside the function it does not. I know that an old school concatenated SQL string can be passed like this, but what is the right way to handle this with prepared statements?
function validateForm($stmt, $inputType){
// A bunch of stuff here to validate for $inputType.
$stmt->execute();
}
$editSQL = "UPDATE mytable SET input1 = ?, input2 = ?, input3 = ? WHERE thisID = ?";
$stmt = $conn->prepare($editSQL);
$stmt->bind_param('sibi', $input1, $input2, $input3, $thisID);
$input1 = $vPara[1][5];
$input2 = $vPara[2][5];
$input3 = $vPara[3][5];
$thisID = $_SESSION['thisID'];
validateForm($stmt, $inputType);
The specific error I get is:
Fatal error: Call to a member function execute() on a non-object
I don't see why it could potentially not work.
You mentioned that if you use execute outside of this function it works. So leave it the way it works because That's recommended due to Single responsibility principle.
Your validator should not be responsible for executing statements but
only for what its name says = validation.
The only thing that validator should do is to return true or false
and upon that decision, you should make execution or not
so change your code to the following:
<?php
function isFormValid($inputType)
{
// A bunch of stuff here to validate for $inputType.
if (//test cases) {
$validationResult = true;
} else {
$validationResult = false;
}
return $validationResult;
}
$editSQL = "UPDATE mytable SET input1 = ?, input2 = ?, input3 = ? WHERE thisID = ?";
$stmt = $conn->prepare($editSQL);
$stmt->bind_param('sibi', $input1, $input2, $input3, $thisID);
$input1 = $vPara[1][5];
$input2 = $vPara[2][5];
$input3 = $vPara[3][5];
$thisID = $_SESSION['thisID'];
if(isFormValid($inputType)) {
$stmt->execute();
} else {
//do error processing echo, trow exception etc
}
?>
Note that I changed the validator name, so now it really expresses what it does, instead of being called validateForm but actually doing also a statement execution.
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 7 years ago.
(Edit:Guys, Before jumping to any conclusions, I'm asking how do you escape a query variable from the Example#2 from php.net website. I tried lot of ways but they all gave me errors. If you can please read that Example and post your version of that exact Example#2. Also please read about why they have that example there.)
I was searching for a reliable 'row:count' method to use with PHP PDO across multiple database types, and came across below code from php.net
http://php.net/manual/en/pdostatement.rowcount.php (See Example:#2)
It says to do a row count to see if an entry exists in a database using a SELECT statement, the error proof method is to use PDO::query() instead of PDOStatement::fetchColumn().
My question is I know how to bind and execute with PDO, but I don't know how to assign a user submitted variable($username) to this $sql statement and escape it successfully?
Is it possible to bind parameters to this $sql mehod using PDO?
try{
$conn = new PDO($dsn, $db_username, $db_password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->db = $conn;
} catch(PDOException $e){
echo 'Error:'.$e;
}
public function usernameExists($username){
//Check db for a match.
$sql = "SELECT * FROM users WHERE username = '".$username."'";
$results = $this->db->query($sql);
if($results->fetchColumn() > 0){
//Matching username found in the db
return true;
}else{
//No matching username in db
return false;
}
}
You're looking for bindValue. With it, you can use a placeholder when writing your query, then pass the user's input afterward.
For example:
public function usernameExists($username){
//$result = $this->db->query('SELECT * FROM users WHERE username = ');
//Check db for a match.
$sql = "SELECT * FROM users WHERE username = :username";
$s = $conn->prepare($sql);
$s->bindValue(':username',$username);
$s->execute();
$results = $s->fetchAll();
if(count($results) > 0){
//Matching username found in the db
return true;
}else{
//No matching username in db
return false;
}
For more info, see the PHP manual.
You're going to want to use a parameterized query like this:
<?php
$value = "whatever";
$stmt = $dbh->prepare("SELECT * FROM TABLE_NAME where column_name = ?");
if ($stmt->execute(array($value))) {
while ($row = $stmt->fetch()) {
print_r($row);
}
}
?>
If you really wanted to quote+escape the string, then that's possible too. It even looks somewhat more legible with complex variable interpolation than your original string patching:
$sql = "SELECT * FROM users WHERE username = {$this->db->quote($username)}";
// ->quote itself adds ↑ 'quotes' around
Now of course: don't do that. Use a placeholder, and pass it per ->execute([$var]); instead. Strive for consistency.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
So I have this code:
<?php
if (!isset($_GET['email']) && !isset($_GET['key'])) {
echo 'NOT ALLOWED TO ACCESS PAGE';
}
if (isset($_GET['email']) && isset($_GET['key'])) {
$email = $_GET['email'];
$regKey = $_GET['key'];
$query = mysql_query("SELECT * FROM `users` WHERE `email`='$email' AND `regRandom`='$regKey'");
if ($query == $regKey) {
mysql_query("UPDATE `users` SET `activated`=1 WHERE `email`='$email'");
if (mysql_query("SELECT activated FROM users WHERE activated='1'")) {
echo file_get_contents("http://TheMegaHouse.com/pageContent/head.php");
echo file_get_contents("http://TheMegaHouse.com/pageContent/notLoggedIn/topNavBar.php");
echo file_get_contents("http://TheMegaHouse.com/pageContent/header.php");
echo 'PASSED';
footer();
} else {
activationFail();
}
} else if ($regKey !== $query) {
echo 'FAIL';
}
}
?>
The thing is that in my database, the value that is in the regRandom column is in fact equal to the value in the key variable in the url but for some reason it is echoing out "FAIL" instead of "PASSED".
Any suggestions on what I am doing wrong, a better way of doing what I want to do or any suggestions?
Always read manual first:
http://php.net/manual/en/function.mysql-query.php
This line of code:
mysql_query("SELECT * FROM `users` WHERE `email`='$email' AND `regRandom`='$regKey'");
Is returning you resource, instead of variable you are lookng for.
Small fix for you:
list($regRandom) = mysql_fetch_row(mysql_query("SELECT regRandom FROM `users` WHERE `email`='$email' AND `regRandom`='$regKey'"));
if ($regRandom == $regKey) {
// magic
And another two things:
mysql_* functions are deprecated
i strongly recommend you to read about SQL Injections.
You should not be using the deprecated mysql_* functions but switch to PDO or mysqli and prepared statements.
However, the problem you are having is that you are comparing a resource to a sent-in variable.
My guess is that $regKey is an integer and $query is the result of a mysql query. You need to fetch a row from the result-set and compare a specific value from that row to your $regKey.
Correct me if Im wrong, but $query results is a resource? You haven't done anything with it.
I would suggest just doing a simple mysql_num_rows() check like this:
$query = mysql_query("SELECT * FROM `users` WHERE `email`='$email' AND `regRandom`='$regKey'");
if (mysql_num_rows($query) == 1) {
Its pointless to check again because you are already checking in the SQL query :) So simply check the number of rows returned. 0 = not found, 1+ = results :)
My goal is to display the profile of a user. I have this function:
function get_profile($un) {
if($registerquery = $this->conn->query("SELECT * FROM table WHERE usr = '".$un."' ")){
return $profile = mysql_fetch_array($registerquery);
}
}
Then the display snippet:
<?php $profile = $mysql->get_profile($un);
foreach($profile as $key => $value){
echo "<span>".$key.': '.$value."</span><br />";
}
?>
But I get: "Warning: Invalid argument supplied for foreach() in..."
Help pls???
You need to see if the result was a success or not
if (gettype($result) == "boolean") {
$output = array('success' => ($result ? 1 : 0));
}
And you need to cycle through it if it's a resource type...
if (gettype($result) == "resource") {
if (mysql_num_rows($result) != 0 ) {
while ($row = mysql_fetch_assoc($result)) {
$output[] =$row;
}
}
}
I chopped up some real code that does basically everything pretty awful for you because I can't release it, sorry.
Check the result of get_profile, as it will return null if the query failed. You can't loop over null.
Be very very careful here. You are passing a raw string into the query function without escaping it and without using a parameterized query. Use mysql_escape_string around $un in your query. Your code flaw is called a sql injection attack.
Someone could pass their username as this
myusername'; update users set password = '';
And blank all passwords, thereby allowing themselves to access any account. Other similar shady attacks are equally likely.. you can basically do anything to a database with sql injection attacks.
I Agree with Anthony Forloney. The following code is just returning TRUE or FALSE depending on wether loading the $profile variable worked:
return $profile = mysql_fetch_array($registerquery);
You don't need $profile. You can eliminate it as such:
return mysql_fetch_array($registerquery);
The function will return the array and then when you call the function later you can load it's return value into $profile as you do with the following:
$profile = $mysql->get_profile($un);
Try this:
function get_profile($un) {
if($result = $this->conn->query("SELECT * FROM table WHERE usr = '".$un."' ")){
return $result->fetchArray(MYSQLI_ASSOC);
}
return array();
}
You're mixing MySQLi and MySQL functions and you can't do that. And, the last line of this code will return an empty array if the query does not work, rather than return null.
It is probably empty ($profile). Print the value of "count($profile)"
I have found that the easiest way to loop through mysql results is to use a while loop:
$select = "SELECT * FROM MyTable";
$result = mysql_query($select);
while ($profile = mysql_fetch_array($result)) {
$name = $profile['name'];
...
}