I have php script which receives many variables from JavaScript search form. The thing is some of these variable could be empty so I have to check each one before querying it. e.g: user could enter the name and id of student and leave the gender field empty, so how I supposed to write the query? I've read that I might need use append but I have no idea how to do that. Any other better idea ?
piece of script:
$name = ($_GET['name']);
$id = ($_GET['id']);
$gender = ($_GET['gender']);
(!$con) {
throw new Exception("Error in connection to DB");
}
$query ="SELECT grade FROM students WHERE name ILIKE '%$name%' ";
$result = pg_query($query);
EDIT
Okay if I use empty and isset functions, then I have to check every variable and write new query? How can I update the original query after checking ?
With PHP you can use empty and isset as such:
if (!isset($_GET['name']) || empty($_GET['name'])) {
// Error detection, this field isn't available
}
Please note that isset is actually redundant in this example, as empty will return false if it is not set.
Documentation can be found here and here
empty ( )
Determine whether a variable is empty :
http://php.net/manual/en/function.empty.php
isset ( )
Determine if a variable is set and is not NULL :
http://php.net/manual/en/function.isset.php
You can just check the variable content like this:
if (!empty($_GET['name'])) {
// make your query
}
Think outside the box.
<?php
$first = TRUE;
$var_names = array('name', 'age', 'gender');
$query = "SELECT * FROM table WHERE"
foreach( $_GET as $key => $value ) {
if( in_array($key, $var_names) && !empty($_GET[$key]) ) {
if( $first ) {
$query .= sprintf(" %s = '%s'", $key, $value);
$first = FALSE;
} else {
$query .= sprintf(" AND %s = '%s'", $key, $value);
}
}
}
if( $first ) { die('no parameters given, query will error out.'); }
echo $query;
This is also terribly insecure for SQL injection, but I'm not going to implement parameterized queries here.
Related
This question already has answers here:
Single result from database using mysqli
(6 answers)
Closed 2 years ago.
I am trying to write a function that will check for a single value in the db using mysqli without having to place it in an array. What else can I do besides what I am already doing here?
function getval($query){
$mysqli = new mysqli();
$mysqli->connect(HOST, USER, PASS, DB);
$result = $mysqli->query($query);
$value = $mysqli->fetch_array;
$mysqli->close();
return $value;
}
How about
$name = $mysqli->query("SELECT name FROM contacts WHERE id = 5")->fetch_object()->name;
The mysql extension could do this using mysql_result, but mysqli has no equivalent function as of today, afaik. It always returns an array.
If I didn't just create the record, I do it this way:
$getID = mysqli_fetch_assoc(mysqli_query($link, "SELECT userID FROM users WHERE something = 'unique'"));
$userID = $getID['userID'];
Or if I did just create the record and the userID column is AI, I do:
$userID = mysqli_insert_id($link);
Always best to create the connection once at the beginning and close at the end. Here's how I would implement your function.
$mysqli = new mysqli();
$mysqli->connect(HOSTNAME, USERNAME, PASSWORD, DATABASE);
$value_1 = get_value($mysqli,"SELECT ID FROM Table1 LIMIT 1");
$value_2 = get_value($mysqli,"SELECT ID FROM Table2 LIMIT 1");
$mysqli->close();
function get_value($mysqli, $sql) {
$result = $mysqli->query($sql);
$value = $result->fetch_array(MYSQLI_NUM);
return is_array($value) ? $value[0] : "";
}
Here's what I ended up with:
function get_col($sql){
global $db;
if(strpos(strtoupper($sql), 'LIMIT') === false) {
$sql .= " LIMIT 1";
}
$query = mysqli_query($db, $sql);
$row = mysqli_fetch_array($query);
return $row[0];
}
This way, if you forget to include LIMIT 1 in your query (we've all done it), the function will append it.
Example usage:
$first_name = get_col("SELECT `first_name` FROM `people` WHERE `id`='123'");
Even this is an old topic, I don't see here pretty simple way I used to use for such assignment:
list($value) = $mysqli->fetch_array;
you can assign directly more variables, not just one and so you can avoid using arrays completely. See the php function list() for details.
This doesn't completely avoid the array but dispenses with it in one line.
function getval($query) {
$mysqli = new mysqli();
$mysqli->connect(HOST, USER, PASS, DB);
return $mysqli->query($query)->fetch_row()[0];
}
First and foremost,
Such a function should support prepared statements
Otherwise it will be horribly insecure.
Also, such a function should never connect on its own, but accept an existing connection variable as a parameter.
Given all the above, only acceptable way to call such a function would be be like
$name = getVal($mysqli, $query, [$param1, $param2]);
allowing $query to contain only placeholders, while the actual data has to be added separately. Any other variant, including all other answers posted here, should never be used.
function getVal($mysqli, $sql, $values = array())
{
$stm = $mysqli->prepare($sql);
if ($values)
{
$types = str_repeat("s", count($values));
$stm->bind_param($types, ...$values);
}
$stm->execute();
$stm->bind_result($ret);
$stm->fetch();
return $ret;
}
Which is used like this
$name = getVal("SELECT name FROM users WHERE id = ?", [$id]);
and it's the only proper and safe way to call such a function, while all other variants lack security and, often, readability.
Try something like this:
$last = $mysqli->query("SELECT max(id) as last FROM table")->fetch_object()->last;
Cheers
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);
}
}
}
}
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?
I'm running a function that checks whether or not an user has already submitted a question. I've narrowed the problem down to my function which runs a query code. For some reason it is not working. The function does work when the part that involved AND user_requester... is not there. I'm sure it's some sort of syntax error but I don't get a response from the error reporting. Here is the code below:
function question_exists ($question, $user_id) {
$question = sanitize($question);
$query = mysql_query("SELECT COUNT(`primary_id`) FROM `requests` WHERE
`question_asked`= '$question' AND `user_requester` = $user_id");
return (mysql_result($query, 0) == 1) ? true : false;
}
Clarification: I want to prevent an user from submitting the same question twice. That is the purpose of adding the AND section to the where clause in the query. When I do add the AND section, everything goes to pieces and the user can submit the same question anyways.
I would try doing all steps separately so you can test the result of each operation individually. Your return line is handling a lot of things and so it's hard to tell where you problem is. Something like this...
function question_exists( $question, $user_id )
{
$question = sanitize( $question );
$user_id = (int) $user_id; // additional sanitization in case you didn't do it already.
$sql = "SELECT COUNT(`primary_id`) FROM `requests` WHERE
`question_asked`= '$question' AND `user_requester` = $user_id";
$result = mysql_query( $sql );
if ( !$result ) {
// Note: this would be better sent to an error handling function, this is just for simplicity's sake.
echo 'Mysql query error: ' . mysql_error();
exit;
}
$row = mysql_fetch_row ( $result );
if ( $row ) {
return true;
} else {
// temporary debug code
echo "unknown error</ br>\n";
echo "sql: " . $sql . "</ br>\n";
echo "<pre>";
var_dump( $row );
echo "</pre>";
exit();
// real code for after problem is solved
return false;
}
}
If this still doesn't help and you haven't already, dump your $question and $user_id vars to make sure that you are receiving them and your sanitize function isn't doing something incorrectly. Note, I have not run this code so there may be syntax errors.
What kind of error reporting are you referring to? A query failing will not trigger any PHP errors/warnings. You'd need somethign like
$query = mysql_query(...) or die(mysql_error());
to see what really happened.
$query = mysql_query("SELECT COUNT(`primary_id`) FROM `requests` WHERE
`question_asked`= '$question' AND `user_requester` = {$user_id}");
Add curly braces to your variable in the query.
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'];
...
}