Here is my problem,
Not using prepared statements I can do it just fine, for example,
$qry = "SELECT * FROM accounts WHERE email = '$email'";
$result = mysql_query($qry);
$account = mysql_fetch_assoc($result);
echo '<p>Welcome <strong>' . $account['username'] . '</strong>, Have a good day! And dont forgot your id ' . $account['id'] . '.</p>';
Considering an email does match a row on the mysql database, then I can with ease echo any other column where the email matches by simply doing $account['gender'], $account['age'] for example.
I am having alot of trouble doing it OO, here is my attempt;
$q = $dbc -> prepare ("SELECT * FROM accounts WHERE email = ?");
$q -> bind_param ('s', $email);
$q -> execute();
$q -> bind_result();
$info = $q -> fetch();
echo '<p>Welcome ' . $info['username'] . '.</p>';
Doing it with the first method I can display any information from any column where the email matches for that row, I switched to prepared statements for security, but I am thinking of switching back with the hassle it is causing!
bind_result takes parameters. You pass it the variables you want it to set, then you call fetch.
$q->bind_result($username);
$q->fetch();
echo $username;
For this to work, you need to change SELECT * to the fields you want, ie SELECT username.
If you still need to use SELECT *, you can do this:
$q->execute();
$r = $q->get_result();
while($row = $r->fetch_array(MYSQLI_ASSOC)){
}
Good old MySQL extension does not support prepared statements so you must have switched to another extension you don't mention. If it happens to be mysqli, you're out of luck: it only supports associative arrays when you don't use prepared statements.
My advise is to try out PDO. The MySQL driver is stable and it has a great API you can reuse for other DBMS engines.
Related
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.
I would like to get the number of lines returned by a select query in PHP. I have the following code:
$connection = new mysqli($server_name, $server_login, $server_password, $dbName);
if (!$connection) {
echo "error";
die("Connection failed. ".mysqli_connect_error())
}
//...
$command = "SELECT player_id FROM Player WHERE player_login = '" . $login."' AND player_password= '".$password."' ";
$result = mysqli_query($connection, $command);
echo num_rows($result);
I also tried with mysqli_stmt_num_rows() and mysqli_num_rows() but my result is always null (no result actually).
Do you know why?
There are a few ways to get the number of rows returned, the most common ones are to run COUNT(*) in MySQL, but there's also mysqli_num_rows($result) (not num_rows() like you used, unless you created that function yourself). mysqli_stmt_num_rows() will only work when you're using prepare() instead of query().
In ordre to use COUNT(*) you have to run and fetch the query first, while mysqli_num_rows() is a constant returned by the MySQLiResult object, which you can use if the query didn't fail.
I modified the piece of code you've got to check if the query actually succeeded, mysqli_num_rows() won't work if the query failed.
$command = "SELECT player_id FROM Player WHERE player_login = '" . $login."' AND player_password= '".$password."' ";
if ($result = mysqli_query($connection, $command)) {
echo mysqli_num_rows($result);
} else {
/* Query failed */
echo "There was an error with the query: $command";
echo "<br />".mysqli_error($connect);
}
Or you can use COUNT(*), but then you'll have to fetch the results first.
$command = "SELECT player_id, COUNT(*) as cnt FROM Player WHERE player_login = '" . $login."' AND player_password= '".$password."' ";
if ($result = mysqli_query($connection, $command)) {
$row = mysqli_fetch_assoc($result);
echo $row['cnt'];
} else {
/* Query failed */
echo "There was an error with the query: $command";
echo "<br />".mysqli_error($connect);
}
You should also note that this query is vulnerable to SQL injection, you should learn how to use prepared statements with placeholders to protect yourself against that. The manual on prepare() is a good place to start with that.
You also seem to be storing passwords either in plain-text, or with poor methods (such as md5 or sha1). PHP offer's a built-in function, password_hash()/password_verify() which you should use. If you're below PHP version 5.5, these functions aren't native, but there's a compability pack which can be used instead.
As a final note, mixing object oriented and procedural code will technically work (as the procedural ones in reality call the object oriented ones), but it's considered bad practice. If you connect with an object, continue to use object-oriented code.
References
http://php.net/mysqli-result.num-rows
http://php.net/mysqli-stmt.prepare
http://php.net/password_hash
$command = "SELECT count(*) as numberofrecord, player_id FROM Player WHERE player_login = '" . $login."' AND player_password= '".$password."' ";
Very simple solution:-
Use $result->num_rows in below way:-
if ($result = $mysqli->query("SELECT player_id FROM Player WHERE player_login = '" . $login."' AND player_password= '".$password."'")) {
printf("Select returned %d rows.\n", $result->num_rows);
}
Reference:- http://php.net/manual/en/mysqli.query.php
Note:-
Meanwhile read prepared statement and use them to prevent your code from SQL Injection.
Also always use password hashing mechanism while storing the password (if you used plain password).
I was advised to update my code to prevent sql injections. So here is what I have.
VARIABLE FROM URL
$Idarticle = "5-6142-8906-6641";
THIS WORKS - OLD
$sql2 = "SELECT * FROM articles WHERE IDArticle IN ('{$Idarticle}')";
$results2 = $conn->query($sql2);
$row2 = $results2->fetch_assoc();
THIS DOES NOT WORK - NEW
$sql2 = "SELECT * FROM articles WHERE IDArticle IN ( ? )";
if ($stmt = $conn->prepare($sql2)) {
$stmt->bind_param("s", $Idarticle);
$stmt->execute();
$row2 = $stmt->fetch();
}
MY CONNECTION SCRIPT
$conn = new mysqli($servername, $username, $password, $db);
In the second example I get no results(no errors either) verses in the first it finds the correct row. I have read numerous similar questions previously asked and while there may be an answer out there, I did not find it. I also tried some of those answers without any success. I appreciate any help.
UPDATED CODE PER COMMENTS
$sql2 = "SELECT * FROM articles WHERE IDArticle = ?";
if (!$stmt = $conn->prepare($sql2)) {
if (!$stmt->bind_param("s", $Idarticle));
echo "error: " . $stmt->error;
if (!$stmt->execute());
echo "error: " . $stmt->error;
$row2 = $stmt->fetch();
}
Still not finding the record / no errors being reported
MY SOLUTION
Having spent close to two days researching and trying to solve this issue, I decided mysqli was at the heart of the problem. Why I am sure this issue does have a solution with mysqli, I ended up moving to PDO. I resisted doing this initially but after a few hours of study, it is in my opinion, as well as many others, far better. Bottom line it now works flawlessly with very few changes. My recommendation, If you are struggling with mysqli, switch to PDO.
A BIG THANK YOU TO THOSE WHO TRIED TO HELP
BTW: Is there any special reason for using IN?
"SELECT * FROM articles WHERE IDArticle = ?"
This is your problem:
$row2 = $stmt->fetch();
mysqli_stmt::fetch returns boolean true/false on success, and you're trying to use it as an array for row2
You must bind your results first with mysqli_stmt::bind_result, and then fetch
See this creative answer for how to get an associative array from bind_result
Preferably, if you have the MySQL native driver installed, then you can extract this directly with mysqli_stmt::get_result
Also, you're not checking for statement errors.
if ( !$stmt->bind_param("s", $Idarticle) )
echo "error: " . $stmt->error;
if ( !$stmt->execute() )
echo "error: " . $stmt->error;
And you should make sure you're using PHP error reporting.
If $results1/$results2 is not a typo, then the new code is very different, because there must be two independent queries.
$sql2 = "SELECT * FROM articles WHERE IDArticle IN ( ? )";
if ($stmt = $conn->prepare($sql2)) {
$stmt->bind_param("s", $Idarticle);
$stmt->execute();
}
But it's not clear then what was done with $results2 later in the code. row2 might be totally unrelated to
$row2 = $results1->fetch_assoc();
My question supposed to be simple! although, I couldn't find the correct answer!
I need to retrieve the "hashed password" for the giving "username" from mySql database with php, then I need to store it in a variable, how could I do that?
All what I get is "Resource id #5"!
This is my code:
$query = "SELECT hashed_password ";
$query .= "FROM users ";
$query .= "WHERE username = '{$username}' ";
$query .= "AND hashed_password = '{$hashed_password}' ";
$query .= "LIMIT 1";
$result_set = mysql_query($query);
echo "$result_set";
echo '</br>';
To start off, let's use a MySQL library that supports prepared statements - otherwise, we'll run into SQL Injection issues in the future. Now, back to the actual question / answer.
If we use MySQLi, we have a few functions that will help us. Here's an example of an answer to your question w/ code comments to help walk through it:
// create our db connection
$mysqli = new mysqli('localhost', 'db_username', 'db_password', 'db_table');
// create a Prepared Statement to query to db
$stmt = $mysqli->prepare('SELECT hashed_password FROM users WHERE username = ? LIMIT 1');
// dynamically bind the supplied "username" value
$stmt->bind_param('s', $username);
// execute the query
$stmt->execute();
// get the first result and store the first column in the `$hashed_password` variable
$stmt->bind_result($hashed_password);
$stmt->fetch();
// close our Prepared Statement and the db connection
$stmt->close();
$mysqli->close();
echo $hashed_password;
Check out the PHP Doc for mysqli::prepare() for more examples =]
Note: I highly recommend avoiding the mysql_query() (and family) functions. They are not only deprecated, but they are quite insecure to use.
You need to fetch the data out of the mysql-resource that is returned by a query.
Just pass it through mysql_fetch_assoc($result_set). It will return your data in a nice and ordered arraay, moving ahead one row every call.
Meaning you can do
while ($row = mysql_fetch_assoc($result_set).
Also, please use mysqli. Its basically the same just with mysqli instead of mysql in commands. See the docs here for more info: http://php.net/manual/en/book.mysqli.php
I am writing some SQL and using AdoDb to connect to my database and run the queries and so on. I am using parametrized queries and have run into a snag.
Is their a way to pass an array of values to an in_clause in AdoDb/MySql for parametrization.
My problem is that if I pass a prepared string as the parameter i.e. 'test','test2','test3' it does not work as the library or database auto escapes it and adds external quotes at the start and end so all the internal quotes are then auto escaped thus the query returns nothing as it looks for '\'test\',\'test2\',\'test3\'' as opposed to what I fed it.
UPDATED WITH ANOTHER POSSIBLE METHOD TO ACCOMPLISH THIS
<?php
$in_clause = implode(",", $first_names);
$query = "
SELECT
mytable_id_pk
FROM
mytable
WHERE
FIND_IN_SET(mytable_fname," . $DB->Param('first_names') . ")"
$stmt = $DB->Prepare($query);
$result = $DB->Execute($stmt,array($in_clause));
?>
I would do it this way (as I was googling for a while and google came up with nothing useful):
$count = count($first_names);
$in_params = trim(str_repeat('?, ', $count), ', ');
$query = "
SELECT
mytable_id_pk
FROM
mytable
WHERE
mytable_fname IN ({$in_params});";
$stmt = $DB->Prepare($query);
$result = $DB->Execute($stmt, $first_names);
This should do it...
First a few tips:
Please read carefully the AdoDB documentation on prepared statements.
Never include ; in SQL query strings.
You can try something like this:
$question_marks = substr(str_repeat('?,', count($first_names)), 0, -1);
$query = "SELECT mytable_id_pk FROM mytable WHERE mytable_fname IN (" . $question_marks . ")";
$stmt = $DB->Prepare($query);
$result = $DB->Execute($stmt,$first_names);
WARNING: I haven't tested this (not having a mySQL installation here).