How can I use array values in WHERE clauses? - php

I'm trying to figure out how to use a array variable with a where clause.
when I echo $deader, I get 23,25,43,56,31,24,64,34,ect.. these are id numbers i want Updated
$sql = mysql_query("UPDATE users SET dead='DEAD' WHERE userID ='(".$deader.")' ");
The Array$deader has multiple values of id numbers, it only works and updates the first id# in the $deader Array.
I'm reading that Implode is what I need, but don't know how to get it into a functional format.

Use WHERE ... IN
$sql = mysql_query("UPDATE users SET dead='DEAD' WHERE userID IN (".$deader.")");
Where $deader is in comma separated format. (for example: $deader = '143, 554, 32')
If it is an array you can use $deader = implode(',', $deader); to make it comma separated.
Note:
Please stop using mysql_* functions for new code. The functions aren't maintained anymore and the community has begun the deprecation process. See here for more info about converting this to PDO: How do I convert a dynamically constructed ext/mysql query to a PDO prepared statement? (thanks to PeeHaa)

If $deader is some sort of string of values, you will need to use MySQL IN() condition. Like this
UPDATE users SET dead = 'DEAD" WHERE userID IN ('?', '?', '?')
Where ? are your values. If userID as an INTEGER field, you can omit the single quotes around the values, if it is a string field, they would be required.

I think what you're looking for is the IN keyword in SQL.
UPDATE users set dead='DEAD' where userID in (100,101,102)

Using MySQLi instead of mysql_*
require_once('.dbase'); //contains db constants DB_NAME, DB_USER etc
//using PHP built in connection class mysqli
$mysqli = new mysqli(DB_HOST,DB_UNAME,DB_UPWORD,DB_NAME);
if ($mysqli->connect_errno){
$err = urlencode("Failed to open database connection: ".$mysqli->connect_error);
header("Location: error.php?err=$err");
exit();
}
$deader=implode(',',$deader); //assumes array, sting "143,554,32"
if ($stmt = $mysqli->prepare("UPDATE users SET dead='DEAD' WHERE userID IN (?)"){
//bind variable to statement object
$stmt->bind_param('s',$deader) //var type[string],var to bind
//execute query
$stmt->execute();
//feedback
$rowsAffected = $stmt->affected_rows(); //update doesn't return a result set.
//close statement object
$stmt->close();
}
$mysqli->close();
You guys are hammering on Rickos for using mysql_* but not explaining how to do it otherwise, my point was simply showing how to use mysqli. A prepared statement isn't necessary, but since you marked my comment down (peehaa) for not showing it as a prepared statement, here it is edited as a prepared statement. And it does answer his questions.

Related

Is the in_array function a safe way of blocking code injection/sql injection?

If i have a php file which is receiving a $_GET['value'] is it safe from sql injection or code-injection for me to start my php file with
if (in_array($_GET['value'], $allowed_values);)
{ /* normal page code handling the $_GET['value'] */
} else { unset($_GET['name'])
}
$allowed values is obviously an array of all values which i am expecting as safe for $_Get['value']. Is this still unsafe? Thank you.
Yes, that's a common and safe technique that can be used in situations where query parameters can't be used. For instance, if the value will be used as a table or column name, you can't provide it as a query parameter, you have to substitute it directly into the SQL string. Whitelisting like this is the recommended way to ensure that this is safe.
It depends on the values in the $allowed_values array, and how you are interpolating the value into your SQL query.
For example:
$allowed_values = [ 'a word' ];
if (in_array($_GET['value'], $allowed_values)) {
$sql = "SELECT * FROM mytable WHERE id = {$_GET['value']};";
}
Definitely not safe. It results in the SQL:
SELECT * FROM mytable WHERE id = a word;
This is a syntax error.
Why would you not just use SQL query parameters? Then you don't need to worry if it's safe or not. Query parameters separate the values from the SQL parsing, so there's no way any kind of value can cause SQL injection.
You won't have to have an $allowed_values array. You won't have to remember to check if the GET input is in the array. You won't have to worry about quoting or escaping.
It's true that query parameters only work for values, that is in place of a quoted string literal or quoted datetime literal or numeric literal. If you need other parts of your query to be dynamic, like the table name or column name or SQL keywords, etc. then use an allow-list solution like you are showing.
But the more common case of interpolating dynamic values is better handled by query parameters:
$sql = "SELECT * FROM mytable WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt-execute( [ $_GET['value'] ] );
let's discuss this thing in little details:
Your code is like this :
if (in_array($_GET['value'], $allowed_values);) {
...........
$sql = "SELECT * FROM mytable WHERE id = $_GET['value']";
...........
}
else {
unset($_GET['name'])
}
now let's assume, you have some values :
the in_array() function will allow only some pre-defined values, you couldn't have the option to take custom user input by $_GET, but as only pre-defined values are allowed,any SQL command will be safe inside if statement.
now take this example of $allowed_values array :
$allowed_values = ['some details' , 'another details' ,3, ' 105; DROP TABLE mytable;', 22 , 'ok'];
If any of these array values have a string that can have potential SQL injection capability, then there will be an issue. but I think you will not put any such string in the array $allowed_values. ( in this above-mentioned example, index 3, ' 105; DROP TABLE mytable;' can delete the table mytable ). else the SQL command will be safe.
now you can add an extra layer of safety in the code, by using PDO for any SQL query. (in this example you do not need that, as in_array() function is 100% safe unless you yourself put any malicious code in the array, as per my above-mentioned example). but for other types of user input where you have to do some SQL query depend on the user input, you can use PDO -prepared statement.
a PDO example is this :
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare("INSERT INTO photos (username, kname) VALUES (?, ?)");
$stmt->execute([ $username , $kname ]);
For more info, try w3school link: https://www.w3schools.com/php/php_mysql_prepared_statements.asp

How to insert spatial data in MySQL with PHP?

I want to save my coordinate from my Android application to a MySQL database. For this I created an API in PHP, but my code is not working.
Here is my PHP code:
<?php
include_once 'db.php';
$nop = $_POST['nop'];
$plot_bng = $_POST['plot_bng'];
$result = mysqli_query($con, "INSERT INTO sp_house (geom, d_nop)
VALUES (STGeomFromText('POINT($plot_bng)'), '$nop')");
echo json_encode(array("value"=>1));
mysqli_close($con);
?>
When I try an INSERT query in phpMyadmin, the data is successfully stored in the database.
Check the right property for the columns
First of all, make sure you have created the right spatial columns in the database by using the GEOMETRY keyword.
CREATE TABLE sp_house (geom GEOMETRY, d_nop VARCHAR(255));
Insert data into the database with authentication
After you created the columns with the right property you can insert the data into your database. However, your code is widely open to SQL Injection and other kind of database hackings since you insert data directly without any kind of authentication. In order to avoid it, use prepared statements and the mysqli_real_escape_string function. Also, check that you have the right syntax for the query and replace STGeomFromText to ST_GeomFromText.
<?php
include_once 'db.php';
$nop = $_POST['nop'];
$plot_bng = $_POST['plot_bng'];
// You can also check that the variables are empty or not ...
// Clean the variables and prepare for inserting
$plot_bng = mysqli_real_escape_string($con, $plot_bng);
$nop = mysqli_real_escape_string($con, $nop);
$sql = "INSERT INTO sp_house (geom, d_nop)
VALUES (ST_GeomFromText(POINT(?)), ?)";
// Prepared statement for inserting
$stmt = $conn->prepare($sql); // prepare statement for inserting
$stmt->bind_param("ss",$plot_bng,$nop); // replace question marks with values
$stmt->execute(); // execute command
$stmt->close(); // close connection
echo json_encode(array("value"=>1));
mysqli_close($con);
?>
Reference and further reading
Creating Spatial Columns in MySQL
Populating Spatial Columns
How to avoid SQL Injection?
How to use prepared statements?
You're not writing your var correctly, try like this
$result = mysqli_query($con, "INSERT INTO sp_house (geom, d_nop)
VALUES (STGeomFromText('POINT(".$plot_bng.")'), '".$nop."')");
As you writing it, the vars are just normal text...

PDO fetch multiple records from database

I am writing a pretty basic piece of code to fetch one or (in most cases) multiple rows from a mysql database.
function getschema($mysqli){
$id = $_SESSION['user_id'];
$query = $mysqli->prepare("SELECT a.naam
FROM schemes AS a, aankoop AS b
WHERE b.aankoop_username_id = :userid && b.aankoop_schema_id = a.id");
$query->bind_param(':userid', $id, PDO::PARAM_INT);
$query->execute();
$result = $query->fetchAll();
echo ($result);
}
I get the user id from the session and pull the data with the query in the prepared statement.
This statement is correct. I tried it in phpmyadmin and it returns the correct values.
Now I want to use this function in my HTML like so...
<?php echo getschema($mysqli); ?>
But my code does not return a thing, it even messes up the layout of my html page where I want to show the code.
I think it probably is something with the fetchAll command. I also tried the PDO::Fetch_ASSOC but that did not work either.
In addition, I cannot see the php errors, even when they are enabled in the php.ini file.
Here's what's going on; you're mixing MySQL APIs/functions and those do not intermix.
Replace the :userid (PDO) bind in b.aankoop_username_id = :userid with a ? placeholder
b.aankoop_username_id = ?
Then this line:
$query->bind_param(':userid', $id, PDO::PARAM_INT);
Replace :userid by $id and remove , PDO::PARAM_INT but adding i
$query->bind_param("i", $id);
Sidenote: Make sure that column is int type. If not, use s instead of i.
Replace the line for fetchAll with the loop as outlined in AbraCadaver's answer.
You can't mix MySQL APIs/function, read the following on Stack:
Can I mix MySQL APIs in PHP?
Read up on mysqli with prepared statements and how it works:
http://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php
Checking for errors would have outlined the errors.
http://php.net/manual/en/mysqli.error.php
http://php.net/manual/en/function.error-reporting.php
Instead of echo ($result); do return $result; in your function.
Then to use it you have to loop over the array of rows and echo the column that you want:
foreach(getschema($mysqli) as $row) {
echo $row['naam'];
}
Or assign the function return to a variable and loop over that:
$rows = getschema($mysqli);

Get result of prepared mysqli query in an array instead of binding vars to fields

This yields proper results, but I would like to have the resulting row in an array, instead of binding individual variables to each field, so I can access fields like $row[0] and/or $row["name"].
$idToSearch = 2;
$conn = new mysqli("localhost", "username", "password", "db_people");
$statement = $conn->prepare("SELECT name, age from People where id = ?");
$statement->bind_param("i", $idToSearch);
$statement->execute();
$statement->bind_result($name, $age);
if($statement->fetch()) {
echo "The name is $name and the age is $age. ";
} else {
echo "No person found with that id.";
}
Saw an example about fetch_assoc(), but it used a mysqli_result class which I don't know hot to use and unprepared statements which I'd rather not use.
EDIT: To clarify, I'm fine with a solution whether it uses bind_result or not.
In order to use fetch_assoc you would need to use get_results which would force you to not use the bind which it seems you don't want to do. So I believe what you want to do is explained pretty well by user uramihsayibok in the php docs for the bind_result function, specifically here: http://php.net/manual/en/mysqli-stmt.bind-result.php#92505. They explain how to work around that in order get the results into an array.

Why doesn't this prepare statement work in MYSQLI?

I created this code:
$statement = $db->prepare("SELECT * FROM phptech_contact");
$statement->execute();
$result = $statement->result_metadata();
$object = $result->fetch_object();
print_r( $object );
When I run it, it doesn't work. Can anybody tell me why it doesn't work?
I have 20 rows in this table so data should be returned.
From http://ch.php.net/manual/en/mysqli-stmt.result-metadata.php
Note: The result set returned by mysqli_stmt_result_metadata() contains only metadata. It does not contain any row results. The rows are obtained by using the statement handle with mysqli_stmt_fetch().
As long as you don't need this meta data you don't need to call this method.
$statement = $db->prepare("SELECT fld1, fld2 FROM phptech_contact");
$statement->execute();
$stmt->bind_result($fld1, $fld2);
while ($stmt->fetch()) {
echo "$fld1 and $fld2<br />";
}
But I really dislike the mysqli extension. PDO is much cooler ... ;-)
$db = new PDO('...');
$stmt = $db->prepare("SELECT fld1, fld2 FROM phptech_contact");
$stmt->execute();
while ($obj = $stmt->fetchObject()) {
// ...
}
or
$objs = stmt->fetchAll(PDO::FETCH_OBJ);
if you're trying to get the rows from the database, the function you need is mysqli_stmt::fetch(), not mysqli_stmt::fetch_metadata()
You're also missing a few steps. When using prepared statements, you must specify the fields you would like to return instead of using the star wildcard, and then use mysqli_stmt::bind_result() to specify which variables the database fields should be placed in.
If you're more familiar with the original MySQL extension, prepared statements have a different process to use. If your select statement has a parameter (eg., "WHERE value=?") prepared statements are definitely recommended, but for your simple query, mysqli:query() would be sufficient, and not very different from the process of mysql_query()
I believe the problem is that mysqli_stmt::result_metadata() returns a mysqli_result object without any of the actual results — it only holds metadata.
So what you want to do is use $result = $statement->bind_result(...) and then call $result->fetch() repeatedly to get the results.
One of the comments under the bind-result() article shows how to do this for a query like yours, where you don't necessarily know all of the columns being returned.

Categories