I have a table called Stats. Stats has 4 columns: id, ip, count, and date. count is the number of clicks the ip has clicked on the ads on my site. Each time the user clicks on an ad, their count number will increase by 1. How do I increase their count number by 1 and update that in the database? Here is my code and it's not working for some reason. When I click on the div, it doesn't refresh...so the whole block of code isn't executing. Note that I've already captured the user's ip when they entered my site, this is the part where if they clicked my ad, the count is incremented and updated in the database.
<script>
$(document).ready(function()
{
$("#ad").click(function()
{
<?php
$queryTot = "SELECT `count` AS total FROM Stats WHERE ip = '$ip'";
$resultTot = $db->query($queryTot);
$data = $resultTot->fetch_assoc();
$count = $data["total"] + 1;
$insert = $db->prepare("UPDATE Stats(count) WHERE ip = '$ip' VALUES(?)");
$insert->bind_param('i', $count);
$insert->execute();
$insert->close();
?>
location.reload();
})
})
</script>
There is a lot of points to consider in your answer.
But very possibly you should use an AJAX solution to do it, and avoid every SQL queries in your HTML pages, because keeping SQL queries there definitely is not a good pratice, according all basic security and code maintenance POVs.
It is not possible to re-write your code here rightly without knowing your project structure, or even your idea, and you must take this answer as an important start point.
Basically, you must define in your server-side application a method which returns pure data, in a JSON format for example, and then use AJAX to access this method according an event (a click, for example), receive its response and modify your client-side, probably with jQuery and JS.
I hope this answer can help you.
I've written a short example for you that you could continue to build on to accomplish what you need. Here's the basic idea.
HTML
<input type="hidden" id="ip" value="<?php echo $_SERVER['REMOTE_ADDR'];?>"/>
jQuery
var ip = $('#ip').val();
$(document).ready(function(){
$('#ad').on('click',function(){
$.ajax({
type: 'POST',
url: 'ajaxUpdateDatabase.php',
data: 'ip='+ ip,
success: function(response){
console.log(response)
//send the user to the ad's page here for example
//you could use location.href='url-to-add-here';
//or if you really want to reload the page for a reason I fail to understand, use location.reload();
}
});
});
});
PHP (ajaxUpdateDatabase.php)
//please note that using UPDATE requires that there is previously an entry with this IP address.
//example using PDO...
$sql = 'SELECT * FROM stats WHERE ip = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute(array($_POST['ip']));
if($stmt -> rowCount() > 0){
$sql = 'UPDATE stats SET count = count + 1 WHERE ip = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute(array($_POST['ip']));
}
else{
//ip-address was not found in the database
//insert query goes here
}
Related
So I have a backoffice called biblioteca.php where I have some requests and I can validate them trough a button called "Validar". That button redirects to a page like this: http://localhost/pap_16gpsi21/validacao.php?nproposta=87 where I can fill the form and submit.
What I want is to validate the request related to that url.
Example:
I've a request and his number is 90, I click on "Validar", then redirects me to a page like this http://localhost/pap_16gpsi21/validacao.php?nproposta=90, I fill the form and click submit. Then it updates the request number 90 in the database ($updateEstado = "UPDATE propostas SET validacao='Validado'";)
biblioteca.php
$selectProp = "SELECT nproposta, prioridade,disponibilidade,validacao,
autorizacao,aquisicao,registo,biblioteca,docente
FROM propostas
ORDER BY nproposta DESC";
$resultado = mysqli_query($ligaBD, $selectProp);
if (mysqli_num_rows($resultado) > 0) {
// output data of each row
while($row = mysqli_fetch_assoc($resultado)) {
<td><a class="btn btn-default" href="./validacao.php?nproposta=<?= $row["nproposta"] ?>">Validar</a></td>
valida.php
// gets nproposta from propostas
$npropostaLinha = "SELECT nproposta FROM propostas";
$resultado=mysqli_query($ligaBD, $npropostaLinha);
$nproposta = "";
printf($npropostaLinha);
$row = mysqli_fetch_array($resultado,MYSQLI_NUM);
printf("==> ");
print_r($row[0]);
$nproposta = $row[0];
$insertValidacao = "INSERT INTO validacao
(nproposta,nome_validacao,nif_validacao,
email_validacao,preco_validacao)
VALUES ($nproposta,'$nome_validacao','$nif_validacao',
'$email_validacao','$preco_validacao')";
$updateEstado = "UPDATE propostas SET validacao='Validado'";
$resultado = mysqli_query($ligaBD, $insertValidacao);
$resultado = mysqli_query($ligaBD, $updateEstado);
The problem is that if I have 3 requests (90,91,92) and I decide to validate just the number 91 it updates the first which is the number 90.
Also I know this isnt the safest method but this is just a test.
Hopefully, I explained explicitly. Sorry for any grammatical mistakes. Thank you
You need a couple of changes in your code as there are a few logical mistakes that I think you want to avoid.
You need to target a variable to specify from your SELECT that you desire a specific proposta;
You need, when updating, to specify which row, otherwise you will update every single record in your DB;
For such, go to your valida.php and add the following:
At the very top, check you have the variable ready
if (!isset($_POST['nproposta']) || empty($_POST['nproposta'])) {
//Do here what you desire to stop the script from running. Redirect back if you wish;
echo "No proposal id was found";
die;
}
$nPropostaID = $_POST['nproposta'];
Once you have your ID to target the row in your DB, update your query to consider it;
UPDATE propostas SET validacao='Validado' WHERE nproposta = $nPropostaID
Go to your form view and add below line within the form
<input type='hidden' value="<?php echo $_GET['nproposta']?>" name="nproposta">
NOTE: Because you mentioned you are aware of the SQL injections and this is a test I won't go with those, but always good to remember to be careful with them :) My proposal for the queries is just to get you going and in no way good for a script!
I have made a "live search bar" with php and javascript. if you enter a word in the search bar it searches the database (mysql).
index.php:
<input type="text" onkeyup="getMovie(this.value)"/>
<div id="movie"></div>
javascript.js:
function getMovie(value) {
$.post("getmovie.php",{partialMovie:value},function(data) {
$("#movie").html(data);
});
}
getmovie.php:
include_once "connection.php";
if($_POST['partialMovie']){
$partialMovie = $_POST['partialMovie'];
$sql = "SELECT title FROM movie WHERE title LIKE '%$partialMovie%'";
$stm = $db->prepare($sql);
$result = $stm->execute(array());
while($row = $stm->fetch(PDO::FETCH_ASSOC)) {
echo "<li>".$row['title']."</li>";
}
}
This works, but it is way to slow. I have only 3 "movies" in my database, but it takes like a second or two to show the results.
the titles of the 3 movies are: een twee drie.
but if i type "een" fast, after a second you see een, twee, drie. a second later you see: een twee. and another second later you see: een.
So my question is: is there a way to speed the search up or is there a way to stop searching if you type another letter?
Either lower your expectation, because 1 second for a request's round trip is not very improvable, or get the data as json at page load time and search against locally available json data. But if there are many records this might not be an option.
As you use PDO, bind your parameters to avoid sql injection.
Then use full text search in MySQL (select match against), it will be a lot faster than the like %% approach.
Doc : http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
HTML:
<input type="text" id="movie-autocomplete"/>
<div id="movie"></div>
JS:
$(document).ready(function(){
$('#movie-autocomplete').keyup(function(){
setTimeout(function(){
$.post(
"getmovie.php",
{
partialMovie: $(this).val()
},
function(data) {
$("#movie").html(data);
}
);
}, 500);
});
});
This will create a small delay and post an atual value within the field.
PHP:
include_once "connection.php";
if(!empty($_POST['partialMovie'])){
$partialMovie = $_POST['partialMovie'];
$sql = "SELECT title FROM movie WHERE title LIKE :movie ORDER BY title LIMIT 0, 10";
$stm = $db->prepare($sql);
$result = $stm->execute(array(':movie' => "%{$partialMovie}%"));
while($row = $stm->fetch(PDO::FETCH_ASSOC)) {
echo "<li>".$row['title']."</li>";
}
}
We have to bind the parameter to secure the SQL query and prevent SQL injection. Also You should ensure You have set the PDO to use real prepared statements.
To further speed all the process You should return only JSON data from the PHP and fill in the <ul> within Your JS code...
I have this problem that I have multiple fields that updates a database via an AJAX-call. The AJAX call looks like this:
$(".fresheditable").fresheditor("save", function (id, parsedHtml) {
$.ajax({
url: 'save.php',
type: 'POST',
data: {
id: id,
parsedHtml: parsedHtml
}
});
});
The ID value changes depending on what element is being edited. The problem is when the update gets sent to the save.php document. How do I only run the update with the specific ID?
See my save.php:
if($_POST['id']='link')
{
$link = $_POST['parsedHtml']; //get posted data
// query
$sql = "UPDATE buttons SET linkname=? WHERE id=?";
$q = $conn->prepare($sql);
if ($q->execute(array($link,$_SESSION['button'])))
{
echo 1;
}
}
//The next if-statement could look like this:
if($_POST['id']='contactperson')
{
$contactperson = $_POST['parsedHtml']; //get posted data
// query
$sql = "UPDATE buttons SET contactperson=? WHERE id=?";
$q = $conn->prepare($sql);
if ($q->execute(array($contactperson,$_SESSION['button'])))
{
echo 1;
}
}
If more than one ID is sent to the save.php say link and contactperson both if-statements are true and the update sets the same values because the parsedHtml variable.
Is there anything I can do in save.php that can prevent this? Somehow I need to associate the correct parsedHtml with the corresponding id.
The comparison operator in PHP (as well as in Javascript) is == and not =
if($_POST["id"]=="link")
Is it because you're using single equals in your IF tests, which assigns and returns true as a value exists? Not double-equals for comparison?
E.g.
if($_POST['id']=='link')
not
if($_POST['id']='link')
One thing you can use is data attribute i mean
<span item-data="some_id">data</span> now you can select in jquery, the specific item-data from your html to update.
Use else-if structure.
if($_POST['id']='link') {
}
else if($_POST['id']='contactperson') {
}
When someone clicks a button on my web page, this JavaScript code runs:
function count() {
var xmlHttp = getXMLHttp(); // XMLHttpRequest object
xmlHttp.open("GET", "count.php", true);
xmlHttp.send(null);
}
Then, this PHP script gets executed: (a common)
<?php
mysql_connect("host","username","password");
mysql_select_db('database');
mysql_query('UPDATE table SET field = field + 1');
?>
The problem may vary. Lets say I click ten times, it only registers 8 or something. Sometimes it works, other times it does not.
You want to disable the button for clicking until the Ajax request is complete and a success message was returned. For instance, check the commenting mechanism here on StackOverflow. You can't press it twice, because after the first time it gets disabled.
try {
$pdo = new PDO("mysql:host=localhost;dbname=tests", "user", "pass");
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
//Have PDO throw exceptions on errors. That way you don't miss 'em.
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "UPDATE `table` SET `field` = `field`+1";
$stmt = $pdo->prepare($sql);
$stmt->execute();
}
catch (PDOException $e) {
//In case an error has occurred, it will be caught and handled here.
die("There was an error with the database! " . $e->getMessage());
}
That is how I would have done it in PDO.
There is always a solution...
Quick Fix Solution #
Make Your AJAX call synchronous. Note: This will make the Generate button seem stuck during the duration of execution and I think you don't want that (as you are keeping all the names in JS array for faster loading... Yes i visited your link... thanks for posting it)
function count() {
var xmlHttp = getXMLHttp();
var async = false;
xmlHttp.open("GET", "count.php?" + Math.random, async);
xmlHttp.send();
}
Better Solution
//call submit count every 60 secs, play with it to get a interval that suits you best
window.setTimeout("submitCount();",60000);
var globalCounter = 0;
function count()
{
globalCounter++;
}
function submitCount(){
if (globalCounter > 0)
{
var xmlHttp = getXMLHttp();
var async = false;
var countForPHP = globalCounter;
globalCounter = 0;
xmlHttp.open("GET", "count.php?r=" + Math.random + "&count=" + countForPHP, async);
xmlHttp.send();
}
window.setTimeout("submitCount();",60000);
}
Change your PHP to get countForPHP from Request.QueryString and update SQL accordingly
Note: Counts will be lost when the website is closed and that 60 sec lot is not committed to server. To take care of that you may want to call submitCount on window.onbeforeunload
The problem seems to be the browser loading the result from the cache. Add code to send headers to disable caching of the page when you respond in count.php (from php.net header example):
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
Store individual click (with datetime) in the database instead of updating the field. For that, your count.php need to be changed to insert a record(for one click) into the table.
To get the total no. of clicks, you can use "count(1)" of the table. Since you are inserting the date and time of click, you can get the day/week/month/year wise data clicks from the table.
BTW, UPDATE will lock the record/row while updating it. When more than 1 requests are trying to update the same record at the same time (in case of concurrent requests), update may fail because of locking issue.
Your table(clicks - table name) can be as below.
+-------------+---------------------+
| sourceip | click_date |
+-------------+---------------------+
| 10.32.12.45 | 2012-08-16 13:35:03 |
+-------------+---------------------+
And the query in count.php should be like
insert into clicks(sourceip, click_date) values('10.32.12.45', now());
You can get the source ip (client ip) using php script.
And the below queries give you the no. of clicks per day/month/year.
Day => select date_format(click_date, '%Y-%m-%d') as date, count(1) clicks from clicks group by date_format(click_date, '%Y-%m-%d');
Month => select date_format(click_date, '%Y-%m') as date, count(1) clicks from clicks group by date_format(click_date, '%Y-%m');
Year => select date_format(click_date, '%Y') as date, count(1) clicks from clicks group by date_format(click_date, '%Y');
Try This Out:
$con = mysql_connect("host","username","password");
mysql_select_db('database', $con);
$result = mysql_query("select * from table");
$numrows = mysql_num_rows($result);
if ($numrows!=0){
while ($row = mysql_fetch_assoc ($result)){
$Field = $row['field'];
}
$FieldTwo = $Field+1;
$result = mysql_query('UPDATE table SET field='$FieldTwo');
}
I have a career day registration system that allow a student to select 3 unique career choices and submit the results to a mysql database. However, I would like to limit the selections to 90 people per career choice.
Example career day schedule:
Session 1: Nursing (limit to 90)
Session 2: Military (limit to 90)
Session 3: Pharmacy (limit to 90)
Is it possible to do a mysql count and pass the count value to a javascript variable? Also If the count is > 90 a javascript validation happens and doesn't allow you to save to database.
<?php
$sql = "SELECT * FROM mytable WHERE session1 = 'Nursing';
$query = mysql_query($sql);
$num_rows = mysql_num_rows($query);
?>
<script>
var count = <?php echo $num_rows; ?>
function Form_Validator(editform)
{
if((editform.value_session2.value == "Nursing" && count > 90)) { alert("Nursing is closed!"); return (false); }
return (true);
}
</script>
I've tried this method in several different ways... but the values are not being passed. Please help!
You shouldn't be doing this in javascript as any client side script can be bypassed.
What you need to do is do a count on the number of students enrolled in that course before insertion into the database. If count >= 90, then return an error saying the course is full. If count <= 90, then proceed with a statement that inserts the data, then return a success message.
I would do a simple and structured algorithm to work this out:
1) During page load I would only show the avaliable options.
Do a sql "group by", having all the "counts" and restrict the form appearence.
2) During the form submission check again about the possibility for a new applicant.
Do a simple count again, check if it is possible to receive a new submission. That's it. This would save some concurrency problems and other means of bypassing.
This sounds more secure and clear.
Of course you would script a REST service to chek application avaiability during a form filling moment, but that is more work into something it could be simple.
I understand this post is old, but here is what I did. When the user clicks on the Nursing session:
mysql_select_db($database_mySQLConnection, $mySQLConnection);
$query_registrant_count = sprintf("SELECT user_id FROM user_signup WHERE class_id = %s", GetSQLValueString($colname_registrant_count, "int"));
$registrant_count = mysql_query($query_registrant_count, $mySQLConnection) or die(mysql_error());
$row_registrant_count = mysql_fetch_assoc($registrant_count);
$totalRows_registrant_count = mysql_num_rows($registrant_count);
if ($totalRows_registrant_count > 19) {
$returnToCourseList = "../courseListFileName.php";
header(sprintf("Location: %s", $returnToCourseList . "?alert=" . urlencode("We're sorry, but this class is full. Please select another class or contact us for assistance.")));
exit;
}
Then in courseListFileName.php, use Pekka's suggestion for Handling alerts in php