Im trying to use Jquery UI's autocomplete feature to query usernames on my database. So the user enters a username similar to one on my db and the autocomplete is suppossed to guess what they are looking for in a drop down. Unfortunately, I can't get the backend script to return suggestions.
<?php
sleep( 3 );
// no term passed - just exit early with no response
if (empty($_GET['term'])) exit ;
$q = strtolower($_GET["term"]);
// remove slashes if they were magically added
if (get_magic_quotes_gpc()) $q = stripslashes($q);
$sql = "SELECT * FROM users";
$r = mysql_query($sql);
$items = array();
if ( $r !== false && mysql_num_rows($r) > 0 ) {
while ( $a = mysql_fetch_assoc($r) ) {
$username = $a['username'];
array_push($items, $username);
}
}
$result = array();
foreach ($items as $key=>$value) {
if (strpos(strtolower($key), $q) !== false) {
array_push($result, array("id"=>$k, "label"=>$key, "value" => strip_tags($key)));
}
if (count($result) > 11)
break;
}
// json_encode is available in PHP 5.2 and above, or you can install a PECL module in earlier versions
echo json_encode($result);
/* echo $items; */
?>
The script simply returns an empty array, even when it should return a result. I have no idea what is wrong here..
First let me say, querying the database and returning the entire table to sift through for your results is a poor method. The SQL queries will execute faster if they are filtering the data from the database. You have to call up the data anyways, why not filter it and return only the relevant results?
You need to send the query a Like parameter as in the following:
$sql = "SELECT * FROM users where username like :term";
(I'm using parameterized queries in this case which you should use to protect against SQL Injection attacks.)
You can also use the more precarious method as follows:
$sql = "SELECT * FROM users WHERE username = ". $term;
Reference for Parameterized Queries:
How can I prevent SQL injection in PHP?
Related
I have query in which I would like to pass the result of a MS SQL statement to a variable. Not sure how to do this.
My query:
if($view->id() == 'program_search' &&
!empty($searched_miles_value) &&
!empty($searched_zip_value) &&
($searched_miles_value != 'any')) {
$connection = \Drupal\Core\Database\Database::getConnection();
$result = $connection->query("SELECT to_zip FROM zipmaster_xref WHERE from_zip = '".$searched_zip_value."' AND miles = '".$searched_miles_value."'")-> fetchAll();
$target_zips = $result ; //this line is not working
foreach($result as $zip) {
$target_zips[] = $zip->to_zip;
}
$query->addWhere('new_group', 'node__field_zip.field_zip_value', $target_zips, 'IN');
I want to pass the $result array into $target_zips and loop through it. Can any one help me to fix this?
Thanks!
before fetch your data you have to execute the query for example :
$result = $connection->query("SELECT to_zip FROM zipmaster_xref WHERE from_zip = '".$searched_zip_value."' AND miles = '".$searched_miles_value."'")->execute()->fetchAll();
But this usage is not correct at all.Passing variable to the query directly causing SQL Injection be avoid from this you should use placeholders read the documentations first please.
An example for placeholders :
$query = $database->query("SELECT id, example FROM {mytable} WHERE created > :created", [
':created' => REQUEST_TIME - 3600,
]);
Drupal 8 static query documentation can be found at : https://www.drupal.org/docs/8/api/database-api/static-queries
It seems to be impossible to do this just with SQL statements, so I wrote a php check, which is completely ignored by the script. $resourse array holds the right data.
public function handleUpdates($updates) {
$stmt = $this->database->connect()->prepare("SELECT ? FROM users"); //<-
$stmt->execute(["username"]); //<-
$resource = $stmt->fetch(PDO::FETCH_ASSOC); //<-
foreach ($updates["result"] as $update) {
$text = $update["message"]["text"];
$args = $update["message"]["chat"]["username"];
if ($text === "/start") {
if ($resource['username'] !== $args) //this here is ignored
$this->database->add($args);
}
}
}
From what I remember about PDO/SQL (I moved to MVC/Doctrine a while back), this part seems a little redundant
$stmt = $this->database->connect()->prepare("SELECT ? FROM users"); //<-
$stmt->execute(["username"]); //<-
and could be replaced with
$stmt = $this->database->connect()->prepare("SELECT username FROM users"); //<-
as you're only ever wanting to get the data found in the username column there's no need to bind it (which isn't fully possible in PDO anyway).
The reason your query fails is that you are using fetch over fetchAll which returns only the first row of results, while this will run it won't give the desired result (which I'm guessing is to check if the username already exists). Even then (as Ivan Vartanyan points out), you would need to foreach or in_array over $resource as it's results are sent as an array anyway.
Realistically you don't need to search and iterate over all the data in PHP, consider searching for your passed username data with SQL instead (code untested);
public function handleUpdates($updates) {
$stmt = $this->database->connect()->prepare("SELECT username FROM users WHERE username = ?");
$stmt->execute(array($update["message"]["chat"]["username"]));
$resource = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$resource) {
foreach ($updates["result"] as $update) {
$text = $update["message"]["text"];
$args = $update["message"]["chat"]["username"];
if ($text === "/start") {
$this->database->add($args);
}
}
}
}
I'm trying to take a query string param such as ?table=products and have mysql return all the rows for the "products" table in mysql. I tried running the code below in my browser, but I just get a blank white page. I know the mysql server/username/pass information is correct, I've tested the query in mysql and it works fine.
I guess I have two question:
What am I doing wrong?
How come I can't see any error messages when php has an issue?
e.g. code:
<?php
// Get query string parameter value
$keys = array_keys($_GET);
$key = $keys[0];
$value = $_GET[$key];
// Setup connection to mysql database
$serverName = "localhost";
$username = "root";
$password = "password";
$dbname = "webserver";
$conn = new mysqli($serverName, $username, $password, $dbname);
// SQL query
$sql = "SELECT * FROM $value";
$result = $conn->query($sql);
// Print results
echo $result;
?>
Follow the instuctions on below link to enable php.ini errors
How do I get PHP errors to display?
VULNERABLE IMPLEMENTATION WARNING
The above comments clearly mention the side effects of this implementation.
Since knowing the actual bug is a developer's right! Continue reading the answer keeping the safety of software and its users in mind.
You are trying to print $result which is not valid since its an object.
You can do the following instead:
$response = array();
$sql = "SELECT * FROM $value";
$result = $conn->query($sql);
// Print results
if ($result) {
while($row = $result->fetch_array(MYSQL_ASSOC)) {
$response[] = $row;
}
}
echo json_encode($response);
What am I doing wrong?
Sadly, pretty much everything.
// Get query string parameter value
$keys = array_keys($_GET);
$key = $keys[0];
$value = $_GET[$key];
You are dereferencing a named value based on its position. And its totally unnecessary. Consider:
$value=$_GET['table'];
...
$conn = new mysqli($serverName, $username, $password, $dbname);
Where is your error checking to see if $conn was initialized?
$result = $conn->query($sql);
again, no error checking.
echo $result;
$result here is a mysqli_result object. You need to call some methods on it to get the data out.
while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
var_export($row);
}
How come I can't see any error messages when php has an issue?
Have you tested that the default handlers produce output in your browser? You're not overriding the config in php.ini in the code you've shown us. Did you check your logs?
ini_set('diplay_error', 1);
error_reporting(E_ALL);
I just get a blank white page
Would it be so hard to put
print "finished";
at the end of the code? Then you'd at least know if the code executed.
The main issue you have right now is you need to get the results
while ($row = $result->fetch_assoc()) {
//do something with row
}
See ( for mysqli->query method )
http://php.net/manual/en/mysqli.query.php
false on failure and mysqli_query() will return a mysqli_result object on success
See ( for the result objects definition )
http://php.net/manual/en/class.mysqli-result.php
Now as others mentioned I would never just concatenate user data into your query. Imagine a hacker knows the name of a valid table, not hard considering your sending it through the request. All they would have to do is send a value like this:
$value = 'real_table; DROP DATABASE';
And your query becomes.
$sql = "SELECT * FROM real_table; DROP DATABASE";
I won't say that this would actually work as there are ( maybe ) some restrictions on running multiple queries in a single request,user permissions etc... That might save your bacon, but I certainly wouldn't risk it.
So you have 2 choices.
Use a white list of tables
Query the DB for the schema
The first one is easy to do, make a list of tables
$whitelist = [
'table1',
'table2'
];
Then compare your user input
$safeTable = false;
if( false !== ($index = array_search($table, $whitelist))) {
$safeTable = $whitelist[$index];
}else{
//log error and
exit();
}
// SQL query
$sql = "SELECT * FROM $safeTable";
$result = $conn->query($sql);
For the second one,
$schema = $conn->query('SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` LIKE "database"');
$whitelist = [];
while ($row = $result->fetch_assoc()) {
$whitelist[] = $row['TABLE_NAME'];
}
$safeTable = false;
if( false !== ($index = array_search($table, $whitelist))) {
$safeTable = $whitelist[$index];
}else{
//log error and
exit();
}
// SQL query
$sql = "SELECT * FROM $safeTable";
$result = $conn->query($sql);
This will return a list of all the tables in that database, from which you can build an array and then compare. The nice thing about the second one is that if you add a table then you don't have to change the code, which may or may not be a good thing. You have to have a user with permission to read from information_schema database. And you have to do an additional query.
-note- I am not directly using the users input, I'm using their input to find my data. It's less prone to breaking when there is a coder error. Consider this:
///all my codes are broken;
--if(!in_array($_GET['table'], $whitelist))) {
-- //log error and
-- exit();
--}
// SQL query
$sql = "SELECT * FROM {$_GET['table']}";
$result = $conn->query($sql);
Against this:
$safeTable = false;
// all my codes are broken
-- if( false !== ($index = array_search($_GET['table'], $whitelist))) {
-- $safeTable = $whitelist[$index];
-- }else{
-- //log error and
-- exit();
-- }
// SQL query
$sql = "SELECT * FROM $safeTable"; //$safeTable is undefined or false;
$result = $conn->query($sql);
Were using our code for inclusion, instead of exclusion. So if it breaks, it's never included. The other way, if it breaks it's never excluded. Which is not a situation we want to be even remotely possible.
I hope that helps you understand some of the pitfalls. The #1 rule for SQL (or anything on the web), is Never Trust the User. Never put their data into your SQL.
Sorry if this is a duplicate, I have tried searching but cannot seem to find an answer. I may just have the piece of code in the wrong place.
I have counted the duplicate values input from various select boxes, which were sent over via $_GET. Using these duplicates, if more than (whatever the set amount is) then it will run through a mysql query. This is all working fine.
The issue is that I need to remove duplicates that are returned from the mysql query. Here is my code:
if ($countGearSelected >= 2) {
$gearSets = array_keys(array_filter(array_count_values($_GET['gearPiece']), function($v) {
return $v > 1;
}));
foreach ($gearSets as $gearSetKey => $gearSetValue) {
$result = mysqli_query($con,"SELECT twoPieceBonus FROM sets WHERE setName='".$gearSetValue."';");
while($row = mysqli_fetch_array($result)){
$twoPieceBonus .= urldecode($row['twoPieceBonus']).'</br></br>';
}
$twoPieceBonus = implode(',',array_unique(explode(',', $twoPieceBonus)));
$twoSelected = substr($twoPieceBonus, 0, -10);
}
}else{
$twoSelected = '';
}
As you can see, I have tried the array_unique option on various other posts on SE but it doesn't appear to be working. I think I may be using it incorrectly?
Using DISTINCT doesn't work in the mysql query, as a few of the "sets" that are being queried have the same result (if that makes sense?).
Any help is very much appreciated.
First: your code is vulnerable to SQL injection: use prepared statements to avoid this.
Secondly, it is often a bad idea to execute a query in each iteration of a loop. And in this case it can be avoided. Instead of an equality comparison in your where clause, you could use the in operator and compare to all gear sets in one go.
This will also solve the matter of getting distinct values. With only one query executing, you can use distinct now.
Here is how the code would look like. I could not test this, but I expect mistakes (if any) can be easily fixed:
$twoSelected = '';
if ($countGearSelected >= 2) {
$gearSets = array_keys(array_filter(
array_count_values($_GET['gearPiece']), function($v) {
return $v > 1;
}
));
// Create comma separated list of question marks
$placeHolders = implode(",", array_fill(0, count($gearSets), "?"));
// Prepare SQL statement with it
$stmt = mysqli_prepare($con,
"SELECT DISTINCT twoPieceBonus
FROM sets
WHERE setName IN ($placeHolders);");
// All gearSet values are strings:
$types = str_repeat("s", count($gearSets));
// Turn the gearSets into references
$gearSetRefs = [];
foreach ($gearSets as $i => $_) {
$gearSetRefs[] = &$gearSets[$i];
}
// Bind arguments
mysqli_stmt_bind_param($stmt, $types, ...$gearSetRefs); // the splat operator
// Now we are all set to (safely) execute the query
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
// Let the result of the URL decoding still be an array
$twoPieceBonus = [];
while ($row = mysqli_fetch_array($result)) {
$twoPieceBonus[] = urldecode($row['twoPieceBonus']);
}
mysqli_stmt_close ($stmt);
// ... and then use implode to insert those HTML breaks
$twoSelected = implode("</br></br>", $twoPieceBonus);
}
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'];
...
}