Database
I have these rows of "api_credit" and "api_select" .
The Value of "api_credit" decrements by '1' when it is triggered by a PHP file with the value called "Selected" in "api_select". IMAGE is attached with my question to get a better idea of DATABASE.
Now , the problem is that when it decrements, it decrements all values in "api_credit" which are "Selected".If one column value decrements to '18' , all other columns value becomes '18' if they are having that "Selected" term.
What i want is all of the values of "api_credit" to be "Selected" and want Database to First decrement value in first column of "api_credit" , when it reaches zero , then it should move-on to the next column of "api_credit" and start decrementing its value and so on .
Can Anyone please please please give me an idea of a PHP code to trigger this database behaviour as i want.
Iam new to MySQL and PHP , This database is keeping me frustrated , So Please Please i request you to help me write code in PHP for this database.
Give me any simple or complicated solution for this , iam sure i'll keep up with you.
CODE :
$sql = "SELECT * FROM site_api WHERE api_select = 'Selected'";
$querya = mysql_query($sql, $con);
if(!$querya)
{echo'no api selected'.mysql_error(); exit;}
$row = mysql_fetch_object($querya);
$api = $row->api_key;
$key = $row->secret_key;
include("network.php");
if (preg_match("/OK/", $result))
{
echo "Data has Not been Sent";
}
else
{
echo "Data has Been Sent.";
}
$cr = $row->api_credit;
$aid = $row->api_id;
$cr = $cr - 1;
if($cr <= 0){
$sql="UPDATE site_api SET api_credit='$cr', api_select='Expired' WHERE api_select='Selected'";
First of all, mysql_* functions are deprecated. Use mysqli_* instead!
Second of all, your code is open to SQL injections, use parameterized statements instead! More info on that in here: How can I prevent SQL injection in PHP?.
Finally, and regarding to your issue, if I get it correctly all you want to do is to decrease the value of the first row which has an api_select value of Selected. There are many ways to do this, but I'll just find what I need using LIMIT 1 first and then use the api_id value of that result (if there is any) to query the UPDATE. Here's what I'd do (not using parameterized statements):
$sql = "SELECT * FROM site_api WHERE api_select = 'Selected' AND api_credit > 0 LIMIT 1";
// I'll get only 1 row or none, and also making sure the api_credit is greater than zero.
$querya = mysqli_query($con, $sql);
if(!$querya){
echo 'No API selected. '.mysqli_error();
exit;
} else if(mysqli_num_rows($querya) == 1){
$row = mysqli_fetch_object($querya);
$api = $row->api_key;
$key = $row->secret_key;
/*include("network.php");
if(preg_match("/OK/", $result)){
echo 'Data has not been sent';
} else {
echo 'Data has been sent.';
}*/
// I'm commenting that out because I don't know where $result is coming from, maybe the included file?
$cr = $row->api_credit;
$aid = $row->api_id;
$sql = "UPDATE site_api SET api_credit = (api_credit - 1) WHERE api_id = '$aid'";
// I'm just decreasing within the SQL, but you can still do this with $cr--; outside, it's ok.
if(mysqli_query($sql)){
echo 'Value has been decreased.';
} else {
echo 'Value has not changed.';
}
} else {
echo 'If you can read this, something\'s really wrong!';
}
You can tweak this so that whenever $cr is equal to 0 at UPDATE time it also changes api_select to Expired as you said in your question.
Related
This question already has answers here:
Can I mix MySQL APIs in PHP?
(4 answers)
Closed 6 years ago.
I am attempting to implement a click count system. I am using the following code in this link Click here to see code, but changing it to modern standards. Initially I received errors for the msqli_real_escape_ string, but I believed I resolved it(no errors). Now, I am not receiving any errors at all, but the query is not sending into my database. I am using ini_set('display_errors', 1);
error_reporting(E_ALL); for error checking. Also I have my $con and session in and ini file that I call, so the session and connection are not issues.
Does anyone see what I am doing wrong or is there a good way I can check to see what isn't working?
//create current page constant
$curPage = mysqli_real_escape_string($con,htmlspecialchars($_SERVER['PHP_SELF']));
//set number of clicks variable to 0
$clicks = 0;
//do not recount if page currently loaded
if($_SESSION['page'] != $curPage) {
//set current page as session variable
$_SESSION['page'] = $curPage;
$click_sql = "
SELECT *
FROM click_count
WHERE page_url = ?
";
if (!$click_stmt = $con->prepare($click_sql)) {
$click_stmt->bind_param("s", $curPage);
$click_stmt->execute();
$num_rows = $click_stmt->fetchColumn();
if (!$click_stmt->errno) {
// Handle error here
}
$stmt->bind_result($click_id, $page_url, $page_count);
} elseif ($num_rows == 0) {
//try to create new record and set count for new page to 1
//output error message if problem encountered
$click_insert_stmt = "
INSERT INTO click_count
(page_url, page_count)
VALUES(?, ?)";
if(!$click_stmt = $con->prepare($click_insert_stmt)) {
$click_insert_stmt->execute(array('$curPage',1));
echo "Could not create new click counter.";
}
else {
$clicks= 1;
}
} else {
//get number of clicks for page and add 1 fetch(PDO::FETCH_BOTH)
while($click_row = $click_insert_stmt->fetch(PDO::FETCH_BOTH)) {
$clicks = $row['page_count'] + 1;
//update click count in database;
//report error if not updated
$click_update_stmt = "
UPDATE click_count
SET page_count = ?
WHERE page_url = ?
";
if(!$click_stmt = $con->prepare("$click_update_stmt")) {
$click_update_stmt->execute(array('$clicks', '$curPage'));
echo "Could not save new click count for this page.";
}
}
}
}
Edit: New Updated Code
// ********Page count************
//create current page constant
$curPage = mysqli_real_escape_string($con,($_SERVER['PHP_SELF']));
//set number of clicks variable to 0
$clicks = 0;
//do not recount if page currently loaded
if($_SESSION['page'] != $curPage) {
//set current page as session variable
$_SESSION['page'] = $curPage;
$click_sql = "
SELECT *
FROM click_count
WHERE page_url = ?
";
if (!$click_stmt = $con->prepare($click_sql)) {
$click_stmt->bind_param("s", $_SERVER['PHP_SELF']);
$click_stmt->execute();
$num_rows = $click_stmt->fetchColumn();
if (!$click_stmt->errno) {
// Handle error here
}
$stmt->bind_result($click_id, $page_url, $page_count);
} elseif ($num_rows == 0) {
//try to create new record and set count for new page to 1
//output error message if problem encountered
$click_insert_stmt = "
INSERT INTO click_count
(page_url, page_count)
VALUES(?, ?)";
if(!$click_stmt = $con->prepare($click_insert_stmt)) {
$click_insert_stmt->execute(array($curPage,1));
echo "Could not create new click counter.";
}
else {
$clicks= 1;
}
} else {
//get number of clicks for page and add 1 fetch(PDO::FETCH_BOTH)
while($click_row = $click_insert_stmt->fetch(PDO::FETCH_BOTH)) {
$clicks = $row['page_count'] + 1;
//update click count in database;
//report error if not updated
$click_update_stmt = "
UPDATE click_count
SET page_count=page_count+1
WHERE page_url = ?
";
if(!$click_stmt = $con->prepare("$click_update_stmt")) {
$click_update_stmt->execute(array($curPage));
echo "Could not save new click count for this page.";
}
}
}
}
It looks like you're doing a lot of stuff like this:
$click_update_stmt->execute(array('$clicks', '$curPage'));
I'm not sure where you picked up this habit of quoting variables as strings, but you need to drop it. '$x' and $x are two hugely different things. In the first case it's literally '$x' and in the second case it's whatever the $x variable happens to represent.
Fix it like this:
$click_update_stmt->execute(array($clicks, $curPage));
Also since you're using prepared statements, which by the way is great, you do not need to and should not manually escape your values. Applying them to placeholders with bind_param is the safe way of doing it. Doing any other escaping mangles the data.
Just bind directly to the source:
$click_stmt->bind_param("s", $_SERVER['PHP_SELF']);
Don't arbitrarily run things like htmlspecialchars on input out of paranoia or because you're doing cargo-cult programming and you saw it done in a YouTube tutorial somewhere. That function is intended to be used to display values only, not store them. Data in your database should be as raw as possible.
There's a lot of problems with this code, and one of them that has me confused is why there's so much code. Remember SELECT * and then binding results to arbitrary variables is trouble, your schema might change and then your code is out of sync. Whenever possible fetch rows as an associative array if doing this, then all you have to worry about is renamed ore removed columns.
The biggest problem is this is subject to race conditions because it doesn't use an atomic increment. When writing counters, always do your updates as operations that are a single statement:
UPDATE click_count SET page_count=page_count+1 WHERE page_url=?
Your approach of reading the count, incrementing it, and then writing it back into the database means that you're inviting problems if another operation runs concurrently, something very likely on click-counter code.
I have a sports games picks application that goes by weeks. Right now if you pick a week that you already picked I get a php error. Instead of that I would like to just display a message to the user saying you have already picked for this week.
Heres the error that I get when I pick for the same week
ERROR: duplicate key value violates unique constraint "user_record_pkey"
DETAIL: Key (username, week_no)=(john, 1) already exists
Heres my code
<?php
session_start();
require_once("dbconnect.php");
$flag = 0;
$row = 1;
// $weekest = $_POST['weekNum'];
$result3 = pg_query($conn, 'INSERT INTO demo.user_record VALUES (\''.$_SESSION['username'].'\','.$_POST['weekNum'].',0,0)') or die(pg_last_error());
//echo $_POST['picks0'];
//echo $_POST['picks1'];
for($row=1;$row<=$_POST['numPicks'];$row++){
$pickName = "picks" . $row;
echo $pickName;
if($_POST[$pickName] == "picks$row")
{
$pick = $_POST['Tname'.$flag];
$flag+=2;
}
else
{
$flag++;
$pick = $_POST['Tname' . $flag];
$flag++;
}
//echo "error2";
$result2 = pg_prepare($conn, "myquery".$row, 'INSERT INTO demo.user_picks VALUES ($1,$2,$3,$4)') or die(pg_last_error());
$result2 = pg_execute($conn, "myquery".$row, array($_SESSION['username'],$_POST['weekNum'], $row, $pick)) or die(pg_last_error());
echo "finished";
}
?>
First, the function pg_query() returns FALSE on error. You need to check for that. There are code examples in the linked documentation.
Second, your code is prone to SQL injection. You shouldn't use pg_query() for this kind of problem. You should use pg_query_params() instead. (Same link. Search for "String interpolation of user-supplied data is extremely dangerous".)
I am really trying to wrap my head around this and failing miserably. What I want to do it build a MySQL query based on the URL parameters passed by the URL. I am trying to create a re usable dynamic script that can do what it needs to do based on the URL parameter.
This is what I have come up with, and it appears that it does what it is supposed to do (no errors or anything) but nothing actually gets inserted in the database. I know somewhere I have made a dumb mistake (or thought something out wrong) so hopefully one of you guys can point me in the right direction.
Thanks!
//List all possible variables you can expect the script to receive.
$expectedVars = array('name', 'email', 'score', 'age', 'date');
// This is used for the second part of the query (WHERE, VALUES, ETC)
$fields = array('uName','uEmail','uScore','uAge','uDate');
// Make sure some fields are actually populated....
foreach ($expectedVars as $Var)
{
if (!empty($_GET[$Var]))
{
$fields[] = sprintf("'%s' = '%s'", $Var, mysql_real_escape_string($_GET[$Var]));
}
}
if (count($fields) > 0)
{
// Construct the WHERE Clause
$whereClause = "VALUES " . implode(",",$fields);
//Create the SQL query itself
$sql = ("INSERT INTO $mysql_table ($fields) . $whereClause ");
echo "1"; //It worked
mysql_close($con);
}
else
{
// Return 0 if query failed.
echo "0";
}
?>
You missed mysql_query($sql):
if(!mysql_query($sql)){
//die(mysql_error());
}
Please consider to use PDO or My SQLi using parametrize query because mysl_* function depreciated.
Your SQL is all wrong. You're using the field = value syntax for an INSERT, then you're concatenating an array as if it were a string ($fields), and you're missing a couple of parentheses around the values.
a couple of things: i've found for php <-> mysql its important to see what's going into mysql and experiement directly with those queries in phpmyadmin when i get stuck.
1 - in my code I output mysql_error() when the query fails or when a debug flag is set. this usually explains the sql issue in a way that can point me to a misspelled field name etc...
2 - this way i can feed that mysql query directly into phpmyadmin and tweak it until it gives me the results i want. (while i'm there i can also use explain to see if i need to optimize the table)
specifics in your code. unlike C languages sprintf is implied. here's how i'd write your code:
// List all possible variables you can expect the script to receive.
$expectedvars = array('name', 'email', 'score', 'age', 'date');
// This is used for the second part of the query (WHERE, VALUES, ETC)
// $fields = array('uName','uEmail','uScore','uAge','uDate');
$fields = array();
// Set only the variables that were populated ...
foreach ($expectedvars as $var) {
if (!empty($_GET[$var])) {
$name = "u" + ucwords($var); // convert var into mysql field names
$fields[] = "{$name} = " . mysql_real_escape_string($_GET[$var]);
}
}
// only set those fields which are passed in, let the rest use the mysql default
if (count($fields) > 0) {
// Create the SQL query itself
$sql = "INSERT INTO {$mysql_table} SET " . implode("," , $fields);
$ret = mysql_query($sql);
if (!$ret) {
var_dump('query_failed: ', $sql, $ret);
echo "0"; // Query failed
} else {
echo "1"; // It worked
}
} else {
// Return 0 if nothing to do
echo "0";
}
mysql_close($con);
I have the following problem. I am trying to write function that imports data from csv file. In this file in price column if there are sign like '<>' it means that price is in U.S. dollars and it needs to be converted. I understand that this variable is presented as a digit. How it could be converted to string? Or why the statement doesn't work at all? As always here is the source code.
$str='<>';
if( $variant['price'] ==$variant['price'].$str)
{
$sql = mysql_query("SELECT rate_to FROM s_currencies WHERE id=1 LIMIT 0, 30 ");
$course= mysql_fetch_row($sql);
//$rate=$course[0];
$variant_price = $item['price']*$course[0];
$variant['price']=$variant_price;
}
Please help!
The code which you have posted will not enter into if condition. Make a check with code.
For eg. if $variant['price'] = '1';
if ('1' == '1<>')
{
}
The above condition will not enter into if statement.
You need to check if that string exists, instead of using your current IF statement. strpos will give you want you need
if(strpos($variant['price'],$str) !== false) // <> is present
{
// run your sql code
}
I'd also suggest getting away from the mysql_* functions as they're deprecated. Look into PDO or mysqli queries, with bound parameters.
$str='<>';
if( stristr($variant['price'],$str){
$sql ="SELECT rate_to FROM s_currencies WHERE id=1 LIMIT 0, 30 ";
$qry = mysql_query($sql);
if ($qry && mysql_num_rows($qry)>0){
$variant['price'] = (str_replace($str,'',$variant['price'])*mysql_result($qry,0,0));
} else {
echo 'error while converting:' . mysql_error();
}
}
As i am trying to increment the counter to plus 1 every time when the user clicks on the image. I have written the following code but it says some error "Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in C:\xampp\htdocs\tkboom\includes\core.php on line 72". Can anyone look into this where i made a mistake..
Actually i have created 2 php files one for incrementing the counter and one for displaying the counter. In core.php file i have written the function and for displaying the count i have created a file called view.php
core.php
function GenerateCount($id, $playCount) {
global $setting;
$counter_query = "SELECT hits FROM ava_games WHERE id=".$_GET['id']."";
$counter_res = mysql_query($counter_query);
while($counter_row = mysql_fetch_array($counter_res)){
$counter = $counter_row['hits'] + 1;
$update_counter_query = "UPDATE ava_games SET hits=".$counter." WHERE id=".$_GET['id']."";
$playCount = mysql_query($update_counter_query);
$playCount = $row['hits'];
}
return $playCount;
// Get count END
}
view.php
<?php
$sql = mysql_query("SELECT * FROM ava_games WHERE published=1 ORDER BY id desc LIMIT 30");
while($row = mysql_fetch_array($sql)) {
$url = GameUrl($row['id'], $row['seo_url'], $row['category_id']);
$name = shortenStr($row['name'], $template['module_max_chars']);
$playRt = GenerateRating($row['rating'], $row['homepage']);
$playCt = GenerateCount($row['id'], $row['hits']);
if ($setting['module_thumbs'] == 1) {
$image_url = GameImageUrl($row['image'], $row['import'], $row['url']);
$image = '<div class="homepage_game"><div class="home_game_image"><img src="'.$image_url.'" width= 180 height= 135/></div><div class="home_game_info"><div class="home_game_head">'.$name.'</div></div><div class="home_game_options"><img class="home_game_options_icon" src="'.$setting['site_url'].'/templates/hightek/images/joystick-icon.png" /> '.$playRt.' <b>|</b> '.$playCt.' plays </div></div>';
echo $image;
}
}
?>
That most likely means that there's an error in the sql statement. You can get more information about the error via mysql_error().
In its simplest form:
$counter_res = mysql_query($counter_query) or die(mysql_error());
(edit: ...simplest form, but with this approach you don't give the application a chance to react to the problem, "die" as in "dead". And mysql_error() can leak too much information to a user of your webservice/website, see https://www.owasp.org/index.php/Top_10_2007-Information_Leakage_and_Improper_Error_Handling)
Your code is also prone to
sql injections, because the $_GET parameter is put into the statement without sanitizing it first
race conditions because you have a compound operation consisting of one SELECT and one UPDATE without any locking mechanism.
This is because you get the error in your SQL query.
I'd change it a little bit:
$counter_query = 'SELECT hits FROM ava_games WHERE id = ' . (int)$_GET['id'];
to make sure you always compare id against integer value.
After all, this query does not look good. First point: why are you using two queries to increment a value? UPDATE ava_games SET hits=hits+1 WHERE id=".$_GET['id'].""should do this in one step. Second point: have you heard about SQL injections? Escape or cast $_GET['id'] to avoid surprises ;)
Convert the value in int first like that:
function GenerateCount($playCount) {
global $setting;
$counter_query = "SELECT hits FROM ava_games WHERE id=".$_GET['id']."";
$counter_res = mysql_query($counter_query);
while($counter_row = mysql_fetch_array($counter_res)){
$counter = intval($counter_row['hits']) + 1;
$update_counter_query = "UPDATE ava_games SET hits=".$counter." WHERE id=".$_GET['id']."";
$playCount = mysql_query($update_counter_query);
$playCount = $row['hits'];
}
return $playCount;
// Get count END
}
and check link:
Convert into int
If mysql_query returns a Boolean, your query failed.
Presuming id is the primary key, you can use the following function to update on a database level which will prevent race conditions:
function GenerateCount($playCount) {
global $setting;
$update_counter_query = "UPDATE ava_games SET hits=hits + 1 WHERE id=".intval($_GET['id'])."";
mysql_query($update_counter_query) or die(mysql_error());
$counter_query = "SELECT hits FROM ava_games WHERE id=".intval($_GET['id'])." LIMIT 1";
list($playCount) = mysql_fetch_row(mysql_query($counter_query));
return $playCount;
// Get count END
}
also note the intval() around the $_GET variable to prevent SQL injection