php counter increment error - php

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

Related

How to Use PHP to Retrieve MySQL IDs With Leading Zeros

I set up a new MySQL database and created some PHP Web pages. The IDs for each entry are composed of three digits and have leading zeros (e.g., 000, 001, 002).
My main page that shows every ID as a separate row in an HTML table works fine -- it displays every entry. But my individual entry page is not returning specific entries. For example, the URL entry.php?id=001 and entry.php?id=002 returns the entry for every ID.
I believe the error is at the beginning of the entry.php code, which looks like this:
$query = 'SELECT * FROM databasetablename';
if (isset($_GET['id']) && is_numeric($_GET['id']))
{
$query .= ' WHERE id = ' . (int)$_GET['id'];
}
$result = mysql_query($query);
while($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
... and the code goes on. But I think the error is in this part.
You are casting $_GET['id'] as int after which $_GET['id'] is now = 1
I assume page IDs in database are not of a numeric type, but of CHAR/VARCHAR/TEXT. In this case you should try this:
$query = 'SELECT * FROM databasetablename';
if (isset($_GET['id']) && is_numeric($_GET['id']))
{
$query .= ' WHERE CAST(id AS INTEGER) = ' . (int)$_GET['id'];
}
$result = mysql_query($query);
As a side note: consider using PDO with parameter binding instead of building queries directly from request parameters. This would be extremely dangerous:
$query = ' WHERE CAST(id AS INTEGER) = ' . $_GET['id'];
EDIT: You could also try using mysql_real_escape_string():
$query .= ' WHERE id = ' . mysql_real_escape_string($_GET['id']);
but in this case you should read the security warning about character sets here: http://php.net/manual/en/function.mysql-real-escape-string.php
EDIT2: Sorry, I cannot write comments at the moment, but since you said that it returns every entry it could only mean that the WHERE condition is not added. Check if you actually receive the "id" request parameter in entry.php by using var_dump($_GET).

Q: MySQL + PHP , Update values in multiple rows triggered by a "uniquevalue"

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.

PHP no error displaying but not getting db fields

My database fields are not populating but the page is confirming that it exists. So the first SQL is working, but the second is not pulling the info. If i take the page check out. It doesn't find the page and redirects to page_not_found. Am I going about this correctly? What am i doing wrong here?
//get page url and query db
$this_page = $_GET['page'];
$this_page = escape_data($_GET['page']);
//Make sure page exist
$SQL_page_exist = "SELECT page_title FROM learn_more WHERE page_title = '$this_page'";
$SPE_result = mysql_query($SQL_page_exist);
if(mysql_num_rows($SPE_result) == 0)
{
echo '<META HTTP-EQUIV="Refresh" Content="0; URL=page_not_found.php">';
}
else {
$SQL =
"SELECT * FROM learn_more AS lm
INNER JOIN learn_more_to_reference_key AS lmtrk
ON lm.id = lmtrk.learn_more_id
INNER JOIN reference_keys AS rk
ON rk.keys_id = lmtrk.reference_key_id
WHERE page_title = '$this_page'";
$result = mysql_query($SQL);
while ($db_field = mysql_fetch_assoc($result));
{
$id = $db_field['ID'];
$main_title = $db_field['main_title'];
$main_content = $db_field['main_content'];
$reference_keys = $db_field['keys_href'];
$sub_title = $db_field['sub_title'];
$sub_content = $db_field['sub_content'];
}
}
mysql_close($dbc);
You should remove the semi-colon after your while statement since it won't execute the following enclosure (meaning your query is fine, but the while statement is invalid).
Also, I'm not sure, but the statement:
$id = $db_field['ID'];
Might generate an error if the mysql field is 'id' (lowercase). While MySQL isn't (usually) case sensitive, php array keys are, so it may be that the key is only available as 'id' and not 'ID'...
Turns out that an empty field from a relational db table (just 1 black field) which is set to not null was causing this undefined break error.. ON ALL PAGES except the home page..
Thank you to all the people who tried to help me.

MySQL Delete Item from Table not working

I am trying to delete a record in my db based on the unique id ($id). Is there something wrong with this code? Probably a simple one for you php pro's.
function delAccount(){
mysql_query("DELETE FROM accounts WHERE id=".$id."LIMIT 1");
}
I get a :
Fatal error: Can't use function return value in write context in
/home/content/53/7311353/html/cca/accounts/include/processAct.php on line 15
My Class that I have powering everything:
class Accounts
{
function Accounts(){
if (isset($_POST['addacct'])){
$this->addAccount();
}elseif(isset($_POST['editacct'])){
$this->editAccount();
}elseif(isset($_POST['delacct'])){
$this->delAccount();
}else{
// redirect if loaded without a POST value set
header("Location: ../index.php?o=illegal&t=nodata");
}
}
You should, first of all, put a space between ".$id." and LIMIT so:
mysql_query("DELETE FROM accounts WHERE id=".$id." LIMIT 1");
Secondly, the $id is NOT available within this function by default. Either do this:
function delAccount($id) {
mysql_query("DELETE FROM accounts WHERE id=".$id." LIMIT 1");
}
and use delAccount($id_parameter); in your script to send the ID along with the function. Or try this:
function delAccount() {
global $id;
mysql_query("DELETE FROM accounts WHERE id=".$id." LIMIT 1");
}
then you can call this function after you set the value of $id somewhere else in your code.
First: is the value for $id actually an id in the database? Second you need a space before "LIMIT", ie:
" LIMIT 1".
Are you sure $id is set?
If $id should be sent to the function as an argument, try this:
function delAccount($id) {
mysql_query("DELETE FROM accounts WHERE id=" . $id . " LIMIT 1");
}
EDIT: You missed a space character between the ID and the LIMIT.
Added some small improvements to the form of the query string:
function delAccount($id) {
mysql_query("DELETE FROM `accounts` WHERE `id` = " . $id . " LIMIT 1");
}
EDIT:
The error you get doesn't come from MySQL itself. Have you checked the returned value. It might return another error, or the returned value might be correct, but used in an erroneous way in later code.
Your error is from the PHP compiler. Are you doing something like this on line 15:
if (delAccount(...) = false) { ... }
? If so, change to ==.
Some hints on how to debug stuff like this.
If you suspect something is wrong, the first thing to do is to output the generated query. Like so:
$query = "DELETE FROM accounts WHERE id=".$id."LIMIT 1";
echo $query; // for debugging
That will show you that at least one thing is wrong with your query: You have a space missing before LIMIT.
mysql_query() returns false if it encounters an error. You can check for that, and output it using mysql_error(). Like so:
$result = mysql_query($query);
if(!$result) trigger_error("Database error!: ".mysql_error());
If $id comes from outside, like the $_GET array, make sure you have tested whether it is an integer before using it in a query to avoid SQL injection.

Problem with MySQL query

I'm trying to debug a MySQL query, and I have trouble understanding why one while loop in my script is not working:
// select db
mysql_select_db($dbname);
for ( $x = $latRange[0]; $x <= $latRange[1]; $x++ )
{
for ( $y = $lngRange[0]; $y <= $lngRange[1]; $y++)
{
$sql="SELECT * FROM $usertable WHERE $xlookup = $x AND $ylookup = $y";
$SQLresult = mysql_query($sql);
while( $row = mysql_fetch_array($SQLresult) )
{
$tmpResult = $row[$popDen];
$result += $tmpResult;
}
}
}
Sample values of the variables described are:
$latRange = array(3,7);
$lngRange = array(9,25);
$popDen = 'ColumnNameIWant'
$xlookup = 'Col1'
$xlookup = 'Col2'
The logic behind my query is that it finds all combinations of x and y, gets the corresponding $popDen value, and adds it to $result. Result is defined at the start of my script, and returned by the program after this loop.
I know that the problem section is my while loop, but I don't quite understand how to fix it as I don't fully understand how mysql_fetch_array functions. I've also tried mysql_fetch_row and my query does not work with this either.
I know from commenting out various chunks of the code, and passing back other numbers that everything else works; it is just this chunk that is failing.
Are there any obvious errors that I am making?
If popDen is a column in your table, you need to get it with:
$tmpResult = $row['popDen'];
and if it is the only value you need, you can simplify / speed up your sql query:
$sql="SELECT `popDen` FROM $usertable WHERE $xlookup = $i AND $ylookup = $y";
Edit: By the way, you might want to initialize your $result variable so that it has a defined / valid / known value if no rows are found.
One obvious error is to use dynamic table names.
This leaves hard to close SQL-injection holes:
Use this code to plug that hole, because mysql-real_escape_string() will not help!
$allowed_tables = array('table1', 'table2');
$clas = $_POST['clas'];
if (in_array($clas, $allowed_tables)) {
$query = "SELECT * FROM `$clas`";
}
See here for more info: How to prevent SQL injection with dynamic tablenames?
And don't forget to always enclose dynamic tablenames in backticks ` or your code will break if you happen to use a reserved word or a number for a table or column name.

Categories