How to use PHP constants in Mysqli prepared statements - php

I'm building an API with a bunch of db queries. To avoid repeating some pre established values in each query I created some PHP constants. However I'm not sure about the right way to include them in Mysqli prepared statements. I know that constants can't be passed by reference. So I wonder if I should create a variable for the query that includes the constants or if I could just pass the string directly with the constants to the prepare() function. So it is okay if I do it like this or should I create a variable and storing the string there prior to calling prepare()?
$stmt = $this->conn->prepare("SELECT city FROM masters WHERE email = ? AND estado != '" . STATE_INACTIVE . "'");
$stmt->bind_param("s", $email );
VERSUS
$query = "SELECT city FROM masters WHERE email = ? AND estado != '" . STATE_INACTIVE . "'";
$stmt = $this->conn->prepare($query);
$stmt->bind_param("s", $email );

Since you're using a constant value, you're not exposing yourself to potential SQL injection attacks by concatenating the value into your query. So, I think what you have is fine. Your other option would be to assign the constant value to a variable and bind it, like this:
$query = "SELECT city FROM masters WHERE email = ? AND estado != ?";
$inactiveState = STATE_INACTIVE;
$stmt = $this->conn->prepare($query);
$stmt->bind_param("ss", $email, $inactiveState);
It's worth pointing out as well here that this is mysqli, not PDO. If you were using PDO you could do this:
$query = "SELECT city FROM masters WHERE email = ? AND estado != ?";
$stmt = $this->conn->prepare($query);
$stmt->bindParam(1, $email, PDO::PARAM_STR);
$stmt->bindValue(2, STATE_INACTIVE, PDO::PARAM_STR);

Related

PHP many variables in WHERE clause MySQL

Here I want to add another variable using AND.
$query = $db->prepare("SELECT *
FROM messages WHERE Subject_Code = ' ".$_SESSION['sub1']." ' ");
I want to add Week = ' ".$_SESSION["weekS1"]." ' to this query using AND. How can I do it?
PHP PDO supports positional (?) and named (:email) placeholders, the latter always begins from a colon and can be written using letters, digits and underscores only. Also note that no quotes have to be ever used around placeholders.
Eg:
The following becomes
$sql = "SELECT * FROM users WHERE email = '$email' AND status='$status'";
To
$sql = 'SELECT * FROM users WHERE email = ? AND status=?';
OR
$sql = 'SELECT * FROM users WHERE email = :email AND status=:status';
With placeholders, you have to prepare it, using the PDO::prepare() method
To get the query executed, you must run execute() method of this object, passing variables in it, in the form of array
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ? AND status=?');
$stmt->execute([$email, $status]);
$user = $stmt->fetch();
// or
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email AND status=:status');
$stmt->execute(['email' => $email, 'status' => $status]);
$user = $stmt->fetch();
Very Good Reference for full tutorial : https://phpdelusions.net/pdo
If you are using PHP5+, You are supposed to bind your parameters outside of the query string when executing your statement.
Example:
$query = $db->prepare('SELECT * FROM messages WHERE Subject_Code = :subj AND Week = :week')
$query->execute(array(
':subj' => $_SESSION['sub1'],
':week' => $_SESSION["weekS1"],
));

Session variable in MySQL query not working using PHP

I have the following MySQL query:
"UPDATE main SET latitude = '{$_POST['latitude']}', longitude = '{$_POST['longitude']}' WHERE idUser = '".$_SESSION['userId']."'""
But this does not work because the userId is always null in the query.
However if I echo $_SESSION['userId'], I get 32 (which is what I want).
And if I change the SQL to:
"UPDATE main SET latitude = '{$_POST['latitude']}', longitude = '{$_POST['longitude']}' WHERE idUser = 32"
It magically works!!!
What am I doing wrong?
EDIT:
I have changed the code to use prepare statements, it still does not work..
global $conn;
$stmt = $conn->prepare("UPDATE main SET latitude = ?, longitude = ? WHERE idUser = ?");
$stmt->bind_param("ssd", $_POST['latitude'], $_POST['longitude'], $_SESSION['userId']);
$stmt->execute();
It only works if I manually write the user Id I got from the echo of $_SESSION['userId']
There is an extra double quote at the end of that string .$_SESSION['userId']."'"", so how that even compiles I have no idea.
You can't bind multiple parameters using a single bindParam() command (you are also using the wrong function bind_param()). Also, the binding is also used for named placeholders. For your prepared statement with unnamed placeholders, simply run execute() using the variables as array, i.e.:
global $conn;
$stmt = $conn->prepare("UPDATE main SET latitude = ?, longitude = ? WHERE idUser = ?");
$stmt->execute(array($_POST['latitude'], $_POST['longitude'], $_SESSION['userId']));
If you want to use bindParam(), then use:
global $conn;
$stmt = $conn->prepare("UPDATE main SET latitude = :lat, longitude = :long WHERE idUser = :userId");
$stmt->bindParam(':lat', $_POST['latitude']);
$stmt->bindParam(':long', $_POST['longitude']);
$stmt->bindParam(':userId', $_SESSION['userId']);
$stmt->execute();
Important note: It seems like you are suppressing error reporting, as using the invalid function bind_param() should have thrown an error. You should enable error reporting in a development environment.
Why not use quotes in the same manner as the $_POST variables? It must have to do with the way you're using quotes inside of that string. I find that less confusion if I always create query strings within single quotes:
'UPDATE main SET latitude = '". $_POST['latitude'] ."',
longitude = '". $_POST['longitude'] ."'
WHERE idUser = '". $_SESSION['userId'];
And, as the comments have mentioned, you should use prepared statements.

Which PDO bind approach should be used for greater security?

I know of two ways to use PDO in PHP to update a MySQL database record. Please could someone explain which one I should use for better security and the difference and I am a little confused.
Method One:
$user = "root";
$pass = "";
$dbh = new PDO('mysql:host=somehost;dbname=somedb', $user, $pass);
$sql = "UPDATE coupons SET
coupon_code = :coupon_code,
valid_from = :valid_from,
valid_to = :valid_to,
discount_percentage = :discount_percentage,
discount_amount = :discount_amount,
calculationType = :calculationType,
limit = :limit
WHERE coupon_code = :coupon";
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':coupon_code', $_POST['coupon_code'], PDO::PARAM_STR);
$stmt->bindParam(':valid_from', $_POST['$valid_from'], PDO::PARAM_STR);
$stmt->bindParam(':valid_to', $_POST['valid_to'], PDO::PARAM_STR);
$stmt->bindParam(':discount_percentage', $_POST['discount_percentage'], PDO::PARAM_STR);
$stmt->bindParam(':discount_amount', $_POST['discount_amount'], PDO::PARAM_STR);
$stmt->bindParam(':calculationType', $_POST['calculationType'], PDO::PARAM_STR);
$stmt->bindParam(':limit', $_POST['limit'], PDO::PARAM_STR);
$stmt->bindParam(':coupon', $_POST['coupon_code'], PDO::PARAM_STR);
$stmt->execute();
Method Two:
$dbtype="somedbtype";
$dbhost="somehost";
$dbname="somedb";
$dbuser="someuser";
$dbpass= "somepass";
$conn = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass);
$title = 'PHP Pattern';
$author = 'Imanda';
$id = 3;
$sql = "UPDATE books
SET title=?, author=?
WHERE id=?";
$q = $conn->prepare($sql);
$q->execute(array($title,$author,$id));
From what I can see, method two does not bind the data, rather insert it directly into the query as an array type. Does this make the script more susceptible to SQL injection or other security risks?
The only difference between the two is that if you pass the array in to the execute function rather than calling bindParam yourself, it treats all parameters as PDO::PARAM_STR automatically, whereas in calling bindParam yourself you could bind them as integers, etc.
From the docs:
input_parameters
An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as PDO::PARAM_STR.
You can also see from the examples there that you can use named parameters (e.g. :limit) when passing the array into the execute function. You don't have to just put ?. In that case you give the array a key:
$sth->execute(array(':calories' => $calories, ':colour' => $colour));
It's mostly a matter of preference. Both protect you from injection.
Though I think it's much easier to force data type with bind(), where as using execute(array()) will be using strings.

PHP MySQLi prepared statements - SELECT

I have problems with my SELECT syntax.
Code:
$stmt = $this->con->prepare("SELECT ? FROM `shop_items` WHERE `id` = ?");
$stmt->bind_param("si", $what, $itemsId);
$stmt->execute();
$stmt->bind_result($res);
$stmt->fetch();
echo $res;
When I want to select "name", it echo "name" instead of result from DB. How to solve it?
Placeholder ? can be used in prepared statement only in substitution of values, not for field names, table names or statement.
You're trying to use it for a field name.
You can build up your query string
$stmt = $this->con->prepare("SELECT " . $what . " FROM `shop_items` WHERE `id` = ?");
but you must be sure you can trust what's inside $what in order to avoid sql injection.
Otherwise you may get all fields
$stmt = $this->con->prepare("SELECT * FROM `shop_items` WHERE `id` = ?");
Fetch results in an associative array (see http://it1.php.net/manual/en/mysqli-result.fetch-assoc.php) and then get only the field value pointed by $what
It looks like you use question mark (?) after SELECT. It should be * symbol where you can select it all from 'shop_items'. You can try again with that.

how to use mysqli_fetch_array with prepared statements

so everyone told me to use prepared statements, but i have no idea what to do now.
$stmt = mysqli_prepare($con, "SELECT * FROM search WHERE `name2` LIKE '?' AND `approved`='approved'");
mysqli_stmt_bind_param($stmt, 's', $name);
/* execute prepared statement */
mysqli_stmt_execute($stmt);
That is my code, how do i make an array from it like
while ($row=mysqli_fetch_array($result))
from non-prepared
Glad to see you are deciding to use PDO!
//using MySQL
//refer here for reference http://www.php.net/manual/en/ref.pdo-mysql.php
$pdo = new PDO('mysql:host=xxx;port=xxx;dbname=xxx', $username, $password)
//write query
$sql = "SELECT * FROM search WHERE `name2` LIKE '?' AND `approved`='approved'";
//tell query what to replace ? marks with
$fill_array = array($name); // one item in array for the one ? in $sql above
//send query to DB for preparation
$prepare = $pdo->prepare($sql);
//send variables to DB, DB will bind them to the proper place and execute query
$prepare->execute($fill_array);
//get your array. I personally recommend PDO::FETCH_ASSOC but you are using ARRAY
$result = $prepare->fetchAll(PDO::FETCH_ARRAY);
echo '<pre>'.print_r($result, true).'</pre>';
Voila!
Please not that you will have to write code to escape $name and check for things like % signs and underscores because if someone literally types in % then the LIKE statement will return all records where approved='approved'

Categories