Arrays in Drupal static queries - php

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

Related

Need a 2023 answer to PDO BIND IN clause [duplicate]

This question already has answers here:
PHP - Using PDO with IN clause array
(9 answers)
Closed 24 days ago.
I did have this code working but it was not secure from SQL injection so I tried to update it. The user submit filter requirements which come from check boxes, I take them from post, and replace them with ?, I then implode, and bind them back together for the IN clause.
I feel like I am a couple of lines of code away from getting this. What am I doing wrong? I have echoed out after implode and it shows the right amount of ? corresponding to the selections. Is the problem in my execute statement?
if(isset($_POST['songgenre'])){
$songgenre = $_POST['songgenre'];
$placeholderssonggenre = array_fill(1, count($songgenre), '?');
$songgenrefilter = implode(',', $placeholderssonggenre);
}else{
$songgenre ='';
$genreempty = '';
}
$sql = "SELECT * FROM music_db WHERE songgenre IN ($songgenrefilter)";
$stmt = $conn->prepare($sql);
$res = $stmt->execute($songgenre);
if ($res !== FALSE) {
$results = $res->rowCount();
echo($results);
} else {
echo "Code Failed";
}
I know really how frustrating it could be. Well, it seems that following things are missing there. Try it:
When you're using the IN clause, you need to pass an array of values to the execute() method, not a single variable. This means that you should be passing $songgenre directly to the execute() method, instead of using it to create the $placeholderssonggenre variable.
You should bind the parameters to the statement before executing it, not after. You can use the bindValue() method to bind the values to the placeholders in the query.
When you execute the statement, you should use the fetchAll() method to retrieve the rows, instead of rowCount().
Here's the correct code:
if(isset($_POST['songgenre'])){
$songgenre = $_POST['songgenre'];
$placeholders = array_fill(0, count($songgenre), '?');
$placeholders = implode(',', $placeholders);
} else {
$songgenre ='';
$placeholders = '';
}
$sql = "SELECT * FROM music_db WHERE songgenre IN ($placeholders)";
$stmt = $conn->prepare($sql);
foreach ($songgenre as $i => $value) {
$stmt->bindValue($i + 1, $value);
}
$stmt->execute();
$results = $stmt->fetchAll();
Another option more elegant
if(isset($_POST['songgenre'])){
$postfilter = [
'songgenre' => ['filter' => FILTER_SANITIZE_STRING] // always sanitize
];
$filter_post_array = filter_var_array($_POST, $postfilter);
$filtered = $filter_post_array['songgenre'];
} else {
$filtered = [];
}
$sql = "SELECT * FROM music_db WHERE songgenre IN (:songgenrefilter)";
$stmt = $conn->prepare($sql);
$stmt->bindValue(':songgenrefilter',implode(',',$filtered);
$stmt->execute();
$result = $stmt->fetchAll();

How to check if column equals a value and do somthing if true? [duplicate]

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

Accessing a MySQL Link Identifier from within a Function

I'm having some difficulty returning an array out of a while lopp which I have in a function. Here is the code I am using. I am meant to be able to return an array of results from the function which contains the id numbers of pictures associated with a particular user id - in this case I want to print_r the array for the user id of 17. When this code isn't in the function it works, but when I place it in the function, no luck. I presume its related to a mistake I am making in the returning of the array. Your help is greatly appreciated.
function picture($id)
{
$sql = "SELECT * FROM avatar WHERE user_id={$id}";
$result = $database->query($sql);
$results = array();
while ($row = mysql_fetch_assoc($result))
{
$results[] = $row;
}
return $results;
}
$results = picture(17);
print_r($results);
Your function can't access your MySQL link identifier
First of all, you're mixing object-oriented paradigm ($database->query($sql)) with procedural paradigm (mysql_fetch_assoc($result)) which will make your code a nightmare to maintain.
Assuming that $database is a mysql_ link identifier, you'll need to pass it into your function in order to access it there.
function getUserAvatar($database, $id){
$sql = 'SELECT * FROM `avatar` WHERE `user_id`=' . intval($id) . ' LIMIT 1;';
$result = mysql_query($database, $sql);
$row = mysql_fetch_assoc($result);
return $row;
}
$results = picture($database, 17);
Don't just copy-paste that, keep reading!
The above will probably work, but if you're allowing a user to pass that user ID into the function, it's quite possible that they'll be able to find a vulnerability to inject an SQL statement of their choice into your MySQL database.
mysql_ functions are deprecated, so you should ideally stop using them and switch to mysqli or PDO. You'll also want to get an understanding of prepared statements in order to prevent SQL injections. If you can't upgrade, look at the mysql_real_escape_string and intval functions and make sure you sanitize all user inputs before processing them.
The resulting code will look something like this, if you switch to mysqli and prepared statements:
function getUserAvatar($db, $userId) {
$stmt = $db->prepare("SELECT * FROM `avatar` WHERE `user_id`=? LIMIT 1;");
$stmt->bind_param("i", $userId);
$stmt->execute();
$res = $stmt->get_result();
return $res->fetch_assoc();
}
$db = new mysqli("localhost", "user", "password", "database");
$result = getUserAvatar($db, 17);
may be you should try this..
function picture($id)
{
$sql = "SELECT * FROM avatar WHERE user_id={$id}";
$result = $database->query($sql);
$row = mysql_fetch_assoc($result);
return $row;
}
$results = picture(17);
print_r($results);

Jquery Autocomplete remote datasource

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?

Is it possible to fetch_object while using bind_param? (PHP/MySQLi)

I have a question for you guys. I'm trying to make the way that I run MySQL as secure as I can. I'm currently wondering if it's possible to fetch an object with MySQLi after I have prepared the statement, binded the parameters, and executed the statement.
Example:
$sql = $mysqli->prepare('SELECT * FROM users WHERE username = ?;');
$sql->bind_param('s', $username);
$username = 'RastaLulz';
$sql->execute();
$object = $sql->fetch_object();
echo $object->mail;
I get the following error:
Fatal error: Call to a member function fetch_object() on a non-object in C:\xampp\htdocs\ProCMS\DevBestCMS\inc\global\class.mysql.php on line 23
However, when I add "$sql->result_metadata();" I don't get an error, but it doesn't return a result (it's just NULL).
$sql = $mysqli->prepare('SELECT * FROM users WHERE username = ?;');
$sql->bind_param('s', $username);
$username = 'RastaLulz';
$sql->execute();
$result = $sql->result_metadata();
$object = $result->fetch_object();
echo $object->mail;
This is how you'd do it without binding the parameters:
$sql = $mysqli->query("SELECT * FROM users WHERE username = 'RastaLulz';");
$object = $sql->fetch_object();
echo $object->mail;
Here's my current MySQL class - just need to get the execute function working.
http://uploadir.com/u/lp74z4
Any help is and will be appreciated!
I had the same question. I found out that I could do the following:
# prepare statement
$stmt = $conn->prepare($sql)
# bind params
$stmt->bind_param("s", $param);
# execute query
$stmt->execute();
# get result
$result = $stmt->get_result();
# fetch object
$object = $result->fetch_object();
I hope that works for you, too.
I just dug around in my Database class and this is how I do it. Honestly I don't remember why I needed to do it this way and there might be a much better way. But if it helps you here is the code. I do vaguely remember being irritated about there not being a simple way to get your results as an object.
// returns an array of objects
public function stmtFetchObject(){
$rows=array(); //init
// bind results to named array
$meta = $this->stmt->result_metadata();
$fields = $meta->fetch_fields();
foreach($fields as $field) {
$result[$field->name] = "";
$resultArray[$field->name] = &$result[$field->name];
}
call_user_func_array(array($this->stmt, 'bind_result'), $resultArray);
// create object of results and array of objects
while($this->stmt->fetch()) {
$resultObject = new stdClass();
foreach ($resultArray as $key => $value) {
$resultObject->$key = $value;
}
$rows[] = $resultObject;
}
return $rows;
}
What is the ';' at the end of your statement? You are giving mysqli an invalid query and so it is not creating an object for you.
The problem is not the fetch_object, but the prepare statement.
Remove the ';' and try again. It should work like a charm.
I've never seen a query end like that.
Try instantiating the variable before binding.
I think its just good practice but use double quotes instead of single quotes.

Categories