Update SQL Query not executing - php

I have a system in which when a user uses a coupon, a "taken" column is filled with a string which I run IS NULL against to render the coupon consumed. My problem is that my update_coupon function is not updating the column as I expect. The first time it worked, but then I must have changed something and subsequent queries no longer work.
Sorry for the noob question. Thank you for any help.
function is_valid_coupon($card_code){
global $db;
$code = sha1($card_code);
$query = 'SELECT * FROM giftcards where card_code = :code';
$statement = $db->prepare($query);
$statement->bindValue(':code', $code);
$statement->execute();
$valid = ($statement->rowCount() == 1);
$statement->closeCursor();
return $valid;
}
function update_coupon($card_code){
global $db;
$code = sha1($card_code);
$query = "
UPDATE `giftcards`
SET taken = used
WHERE card_code = :card_code";
$statement = $db->prepare($query);
$statement->bindValue(':card_code', $code);
$statement->execute();
$statement->closeCursor();
}
Which are executed like so:
if ($card_code){
if (is_valid_coupon($card_code)){
update_coupon($card_code);
}
}

This line is causing the problem:
SET taken = used
you need to put apostrophes before and after used:
SET taken = 'used'

Related

Update dynamically SET statement bind_param not working correctly

I have a simple problem whitch I can't solve, because I am starting with OOP and in the same time with MySQLi.
I need these function universal for everything and I need SET statement dynamically changed.
This is my update function these not working
public function updateUser($user, $pass, $dbSet) {
if($this->getUser($user, $pass) != NULL) {
$sql = $this->connection->prepare("UPDATE users SET ? WHERE user = ?");
$sql->bind_param('ss', $dbSet, $user);
$sql->execute();
$sql->close();
return true;
} else {
return false;
}
}
Variable $dbSet contains different values. For example:
$dbSet = "last_activity = ".$last_activity;
Or complex
$dbSet = "name = ".$newName.", surname = ".$newSurname.", email = ".$newEmail;
But when I change it for one SET statement, it works...
...
$sql = $this->connection->prepare("UPDATE users SET last_activity = ? WHERE user = ?");
...

MySQL Prepared statement confusion

Ok, so I am having a lot of trouble with Prepared statements. I've done hours of research and still can't seem to fully understand everything...
I really feel like I need to understand Prepared statements because I was just about to release a few new free APIs on my website (which require API Key to execute API) but I recently realized how insecure everything is.... I can simply use SQL injection to bypass API Key check, e.g. 'OR'1'='1
Here is how I validate API Key:
$apikey = $_GET['key'];
$sql = "SELECT * FROM `table` WHERE `key` = '$apikey'";
$query = mysqli_query($con, $sql);
if($query)
{
$fetchrow = mysqli_fetch_row($query);
if(isset($fetchrow[0]))
{
echo "API Key is valid!";
}
else
{
echo "API KEY is invalid";
}
}
And like mentioned above this can easily be bypassed by executing my API like this
http://website.com/api.php?key='OR'1'='1
This really scared me at first, but then I did some research and learned a good way to prevent any form of SQL injection is to use prepared statement, so I did a lot of research and it just seems quite complicated to me :/
So I guess my question is, how can I take my above code, and make it function the same way using prepared statements?
Probably everything you need:
class Database {
private static $mysqli;
Connect to the DB:
public static function connect(){
if (isset(self::$mysqli)){
return self::$mysqli;
}
self::$mysqli = new mysqli("DB_HOST", "DB_USER", "DB_PASS", "DB_NAME");
if (mysqli_connect_errno()) {
/*Log error here, return 500 code (db connection error) or something... Details in $mysqli->error*/
}
self::$mysqli->query("SET NAMES utf8");
return self::$mysqli;
}
Execute statement and get results:
public static function execute($stmt){
$stmt->execute();
if ($mysqli->error) {
/*Log it or throw 500 code (sql error)*/
}
return self::getResults($stmt);
}
Bind results to the pure array:
private static function getResults($stmt){
$stmt->store_result();
$meta = $stmt->result_metadata();
if (is_object($meta)){
$variables = array();
$data = array();
while($field = $meta->fetch_field()) {
$variables[] = &$data[$field->name];
}
call_user_func_array(array($stmt, "bind_result"), $variables);
$i = 0;
while($stmt->fetch()) {
$array[$i] = array();
foreach($data as $k=>$v)
$array[$i][$k] = $v;
$i++;
}
$stmt->close();
return $array;
} else {
return $meta;
}
}
Class end :)
}
Example of usage:
public function getSomething($something, $somethingOther){
$mysqli = Database::connect();
$stmt = $mysqli->prepare("SELECT * FROM table WHERE something = ? AND somethingOther = ?");
$stmt->bind_param("si", $something, $somethingOther); // s means string, i means number
$resultsArray = Database::execute($stmt);
$someData = $resultsArray[0]["someColumn"];
}
Resolving your problem:
public function isKeyValid($key){
$mysqli = Database::connect();
$stmt = $mysqli->prepare("SELECT * FROM table WHERE key = ? LIMIT 1");
$stmt->bind_param("s", $key);
$results = Database::execute($stmt);
return count($results > 0);
}
PHP automatically closes DB connection so no worries about it.
$sql = "SELECT * FROM `table` WHERE `key` = ?";
if(stmt = $mysqli->prepare($sql)) {
$stmt->bind_param("i", $apikey);
$stmt->execute();
$stmt->bind_result($res);
$stmt->fetch();
$stmt->close();
}
See more - http://php.net/manual/en/mysqli.prepare.php

is there something wrong with this php code?

is this piece of code correct syntax wise ?
I need to update some fields in a certain row in my database which i can access using email ... so is this right ?
public function storeData($emaill, $servicee, $ratee, $rated_clientss) {
$email = "samy#gmail.com";
$service = "lksdjfsdkljf";
$rate = "good";
$rated_clients = "20";
$stmt = $this->conn->prepare ( "UPDATE users SET service='$service' and SET rate='$rate' and SET rated_clients='$rated_clients' WHERE email='$email'" );
var_dump($stmt->execute ());
if ($stmt->execute ()) {
$data = $stmt->get_result ()->fetch_assoc ();
$stmt->close ();
return $data;
} else {
return NULL;
}
}
Prepared statments to not directly accept user input, instead, you need to pass them as a placeholder: ?, and then use bind_param() to fill in the type and the variable.
Observe:
$stmt = $this->conn->prepare ( "UPDATE users SET service=? and SET rate=? and SET rated_clients=? WHERE email=?" );
$stmt->bind_param('ssss', $service, $rate, $rated_clients, $email);
Now you can correctly ->execute the $stmt.

PHP Slim REST API returns null after calling get function

I have developed a simple REST API using PHP Slim and implemented a simple function which will return a list of track upon matching the album name passed thought REST call.
This is my index.php file for making those rest calls,
http://localhost/my_gallery/v1/tracks/:name
$app->get('/tracks/:name', 'authenticate', function($album_keyword) {
global $user_id;
$response = array();
$db = new DbHandler();
// fetch task
$result = $db->getTracksByName($album_keyword);
if ($result != NULL) {
$response["error"] = false;
$response["album_name"] = $result["album_name"];
$response["track_artist"] = $result["track_artist"];
$response["track_name"] = $result["track_name"];
echoRespnse(200, $response);
} else {
$response["error"] = true;
$response["message"] = "The requested resource doesn't exists";
echoRespnse(404, $response);
}
});
This is the getTracksByName() function for returning a list a tracks after matching the album name,
public function getTracksByName($album_keyword) {
$stmt = $this->conn->prepare(
"SELECT `album`.album_name, `track`.track_artist, `track`.track_name "
. "FROM `category_album` ,`album` , `track` "
. "where `album`.album_id=`track`.album_id AND`album`.`album_name` LIKE ?");
$stmt->bind_param("i", $album_keyword);
if ($stmt->execute()) {
$res = array();
$stmt->bind_result($album_name, $track_artist, $track_name);
$stmt->fetch();
$res["album_name"] = $album_name;
$res["track_artist"] = $track_artist;
$res["track_name"] = $track_name;
$stmt->close();
return $res;
} else {
return NULL;
}
}
Now after making the REST call its returns null values for each track items. Just to mention I've change the SQL query from
... ANDalbum.album_name LIKE ?
to
... ANDalbum.album_id LIKE ?
and its works but for some reason itsn't working with the following query
... ANDalbum.album_name LIKE ?
I'm absolutely new to PHP and any kind of help would be greatly appreciated.
$stmt->bind_param("i", $album_keyword); binds a parameter of type INTEGER. Change to $stmt->bind_param("s", $album_keyword); to bind a parameter of type STRING.
http://php.net/manual/en/mysqli-stmt.bind-param.php
There is two potential issues in your prepared statement code.
First off, you are telling the statement that the parameter is a int:
$stmt->bind_param("i", $album_keyword);
The i indicates Integer. While you want a string (s).
Second issue is that when using LIKE in a prepared statement, you still need the % signs used in a standard LIKE.
For example:
$stmt->bind_param("s", "%$album_keyword%");

user_exists function using mysqli

I';m working on changing my code from using MySQL to MySQLi, and its all seemed to be going fine, but I hit a bit of a wall, I'm currently stuck on changing over my function user_exists and I have tried looking into different reason why and what's going wrong but it seems to be the query, i did var_dump($result) and got the response NULL and was told that its down to my query then, so i tried an sql search on phpmyadmin and got a result so im thinking its down to me binding $username to the ? as the errors i get is of that it cannot find the username im trying to log in with.
function user_exists($username) {
$db = $GLOBALS['db'];
$username = trim($username);
//sql
$sql = "SELECT COUNT(`user_id`) FROM `users` WHERE `username` = ?";
//Prepare
$result = $db->prepare($sql);
//Bind
$result->bind_param('s', $username);
//execute
$result->execute();
//Bind-Results - the 2 codes below are noted out cause im not sure they are needed but have tried with and without them
//$result->bind_result($user_id);
//$result->fetch();
if (false === $result) {
return false;
}
return ($result->num_rows === 1);
}
i can provide the code to my signin.php but im not sure it would be useful as it all worked before i started changing the function.
if someone could point out what, where and why its not working, can you please explain so i can understand so Im good for the future and maybe able to help others out.
You need to call $result->store_result() before checking the number of rows. mysqli_stmt::store_result() will load the result set from the prepared statement so you can access results and properties.
EDIT: This is sort of how I would do it though (untested):
function user_exists($username) {
global $db;
//sql
$sql = "SELECT `user_id` FROM `users` WHERE `username` = ?";
//Prepare
if (!($result = $db->prepare($sql)) return false;
//Bind
if (!$result->bind_param('s', trim($username))) return false;
//execute
if (!$result->execute()) return false;
//Bind-Results
$result->bind_result($user_id);
$result->fetch();
$result->close();
return $user_id ?: false;
}
Here is how my user_exist() function ended up
function user_exists($username) {
$db = $GLOBALS['db'];
//sql
$sql = "SELECT user_id FROM `users` WHERE `username` = ?";
//Prepare
$result = $db->prepare($sql);
//Bind
$result->bind_param('s', $username);
//execute
$result->execute();
//store result
$result->store_result();
if (false === $result) {
return false;
}
return ($result->num_rows === 1);
}
I hope this will help someone. But if any of the code shouldn't be there, i apologise in advance, the code was there for a reason at one point but as im learning all this still, no one advised me that it shouldnt be there.. hope it helps

Categories