Rating script limit votes by ip - mysql

I am trying to limit how many times a ip can vote the images in the database, but I do have problems
Overview of my two tables
T1 (rating)
id votes rating category rating
----------- ---------- ----------- ----------- -----------
T2 (rating_users)
user_id user_ip user_vote user_source
----------- ---------- ----------- -----------
Table 1 -> id
has a relation to
Table 2 -> user_source
I have tried so many different queries the past two days but I just can't figure out how to do this :(
Right now i use this query:
select *
from rating
left join rating_users on rating_users.user_source = rating.id
where rating_users.user_ip is null
or rating_users.user_ip != $ip
order by RAND() LIMIT 1
Lets assume that table1 have 5 rows of data..
if ip1 enters the website and table 2 is empty (truncatet), and he votes all 5 images then the "6th" image will be nothing which is exactly what i want...
But if ip2 enters and table 2 still has the votes from ip1 then ip2 can literally vote as much as he wants because none of the rows are "NULL"...
I am really lost here i have tried to solve this since saturday/sunday night..
Can someone please help me i am getting alot of grey hair here :(
EDIT my code ->
Forside.php (index.php)
<?php
$dbCon = dbCon();
$sql = "SELECT * FROM rating ORDER BY id DESC LIMIT 1";
$result = $dbCon->query($sql);
$result = $result->fetch_object();
$id = $result->id;
//$tal = ip2long($_SERVER['REMOTE_ADDR']);
//$tal = long2ip($_SERVER['REMOTE_ADDR']);
$ip = ip2long($_SERVER['REMOTE_ADDR']);
// CHECKKER OM DEN IP HAR VOTET DETTE BILLEDE
$sql = "SELECT user_ip, user_source, user_vote FROM rating_users WHERE user_ip = $ip AND user_source = $id";
$result = $dbCon->query($sql);
$result = $result->fetch_object();
$rating = $result->user_vote;
if (!empty($result)) {
// echo 'Du har allerede votet dette billede : ' . $rating . "/5";
//IMGINFO
$string = "<div class=\"flex absolute centerAm borc1 boxsb\">";
$string = $string .= "<div id=\"innerVotingWrapper\" class=\"innerVotingWrapper relative flex \">";
$string = $string .= "<div id=\"imgInfo\" class=\"imgInfo absolute top0 right0\">";
$string = $string .= "<div id=\"imgRefresh\">";
$string = $string .= "</div>";
$string = $string .= "</div>";
$string = $string .= "<div class=\"imageWrapper mauto relative fadeInClass\">";
$string = $string .= "<img id=\"imgSrc\" src=\"assets/img/$id.png\" class=\"babeImg borb2 boxsb\">";
$string = $string .= "<div id=\"starWrapper\" class=\"flex absolute left0 bot0 mar10\">";
for ($i = 1; $i <= $rating; $i++) {
$string = $string .= "<div class='voteFull'></div>";
}
for ($i = $rating; $i < 5; $i++) {
$string = $string .= "<div class='voteEmpty'></div>";
}
$string = $string .= "</div>"; //STAR WRAPPER
$string = $string .= "</div>"; //IMAGE WRAPPER
$string = $string .= "</div>";//INNER WRAPPER
$string = $string .= "</div>";//YDRE WRAPPER
//HVIS PERSONEN IKKE HAR STEMT FØR
} else {
$string = "<div class=\"flex absolute centerAm borc1 boxsb\">";
$string = $string .= "<div id=\"innerVotingWrapper\" class=\"innerVotingWrapper relative flex \">";
//IMGINFO
$string = $string .= "<div id=\"imgInfo\" class=\"imgInfo absolute top0 right0\">";
$string = $string .= "</div>";
$string .= "<div class=\"imageWrapper mauto relative fadeInClass\">";
$string .= "<img id=\"imgSrc\" src=\"assets/img/$id.png\" class=\"babeImg borb2 boxsb\">";
//BILLEDE VALUEN
$string .= "<input id=\"imgValue\" class=\"absolute displayn\" type=\"radio\" value=\"$id\">";
//STAR FORM
$string .= "<div id=\"starWrapper\" class=\"starWrapper flex center absolute left0 bot0 mar10\">";
$string .= "<form action=\"\" method=\"post\" class=\"flex flex-drr absolute bot0 left0\">";
for ($i = 5; $i > 0; $i--) {
$string .= "<input id=\"vote$i\" class=\"vote displayn\" type=\"radio\" name=\"vote\" value=\"$i\">";
$string .= "<label for=\"vote$i\"></label>";
}
//SUBMIT FORM
$string .= "<input type=\"submit\" id=\"voteSubmit\" class=\"displayn\">";
$string .= "</form>";
$string .= "</div>"; //starWrapper
$string .= "</div>"; //imageWrapper
$string .= "</div>"; //innerVotingWrapper
$string .= "</div>"; //YDRE NAV TIL AT CENTRERE
}
//COL10
$test = "<div id=\"testid\" class=\"bgw\">";
$test .= "</div>";
?>
<div class="flex">
<div class="col10 bgc2">
<?php echo $test; ?>
</div>
<div class="col90 bgc1 relative vh100">
<?php echo $string; ?>
</div>
</div>
newimage.php
<?php
require_once '../includes/db.php';
require_once '../includes/functions.php';
$dbCon = dbCon();
//$voteValue = filter_input(INPUT_POST, 'voteValue', FILTER_SANITIZE_NUMBER_INT);
//$imgValue = filter_input(INPUT_POST, 'imgValue', FILTER_SANITIZE_NUMBER_INT);
$voteValue = $_POST['voteValue'];
$imgValue = $_POST['imgValue'];
$ip = ip2long($_SERVER['REMOTE_ADDR']);
$stmtt = $dbCon->prepare("INSERT INTO rating_users (user_ip, user_vote, user_source) VALUES (?, ?, ?)");
$stmtt->bind_param('iii', $ip, $voteValue, $imgValue);
$stmtt->execute();
//UPDATERE DATABASED
$stmt = $dbCon->prepare("UPDATE rating SET
votes = votes + 1,
rating = rating + ? WHERE id = ?");
$stmt->bind_param('ii', $voteValue, $imgValue);
$stmt->execute();
//LAV EN SQL QUERY SOM CHECKKER AT id ikke matcher et id allerede votet af den ip
//SENDER NY QUERY AFSTED
$sql = "SELECT * FROM rating INNER JOIN rating_users ON rating_users.user_source = rating.id WHERE rating_users.user_source= $user_source AND (rating_users.user_id= $user_id OR rating_user.ip= $ip ) ";
$result = $dbCon->query($sql);
$result = $result->fetch_object();
$id = $result->id;
//HVIS DEN IKKE ER TOM SKAL DET BILLEDE + RATING DIVS SENDES SOM JSON
$imgSrc = "assets/img/" . $id . ".png";
$arr = array('imgSrc' => $imgSrc, 'id' => $id);
echo json_encode($arr);
Javascript/Ajax
var vote = document.getElementsByClassName('vote');
var voteL = vote.length;
for (let i = 0; i < voteL; i++) {
//SKAL VÆRE LET VALUE
let voteValue = vote[i].value;
vote[i].addEventListener('click', function () {
var imgValue = document.getElementById("imgValue").value;
newImage(voteValue, imgValue);
console.log(vote[i].value);
});
}
function newImage(voteValue, imgValue) {
var http = new XMLHttpRequest();
var url = "pages/newImage.php";
var params = "voteValue=" + voteValue + "&imgValue=" + imgValue;
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function () { //KALDER FUNKTIONEN NÅR DNE ER KLAR
if (http.readyState == 4 && http.status == 200) {
var Data = JSON.parse(this.responseText);
console.log(this.responseText);
var imgSrc = document.getElementById('imgSrc');
imgSrc.src = Data.imgSrc;
var imgValue = document.getElementById('imgValue');
imgValue.value = Data.id;
var ratingValue = Data.rating;
var starWrapper = document.getElementById('starWrapper');
//HVIS IPEN HAR STEMT PÅ BILLEDET BLIVER HANS VOTES RETURNERET TIL VISNING OG IKKE MULIGT AT STEMME
if (Data.rating) {
// OPRETTER VOTED/EMPTY STARS HVIS DER ER VOTET
var string = "";
for (i = 1; i <= ratingValue; i++) {
string = string + "<div class=\"voteFull\"></div>";
}
for (i = ratingValue; i < 5; i++) {
string = string + "<div class=\"voteEmpty\"></div>";
}
starWrapper.innerHTML = string;
} else {
console.log('Data.rating er ikke sat');
}
}
};
http.send(params);
}
var testId = document.getElementById('testid');
testId.addEventListener('click', function () {
console.log('Clicked');
});

Of this is a requirement of the data 1 you s should have a unique constraint on t2 on columns user_source since the user can only vote once, additionally you could add the ip to the unique constraint to limit one vote per ip/user
SELECT *
FROM rating
INNER JOIN rating_users
ON rating_users.user_source = rating.id
WHERE rating_users.user_source= $user_source
AND (rating_users.user_id= $user_id OR rating_user.ip= $ip )
The above query should return zero if the user or ip hasn't voted yet for the current photo
EDIT: I altered the query to limit to the user_id/user_ip and segment to the current photo (user_source). this means you'll have to pass the following to the query $user_source, $user_id, $ip

Related

Echo two SQL query results on a table

I have the following code:
<?php
include_once '../includes/db.inc.php';
$sql = "SELECT * FROM clients ORDER BY nif_id ASC;";
$result = mysqli_query($conn, $sql);
$resultCheck = mysqli_num_rows($result);
if ($resultCheck > 0) {
while ($row = mysqli_fetch_assoc($result)) {
$first = $row["prm_nome"];
$last = $row["apelido"];
$phone = $row['nmr_tlm'];
$email = $row['mail'];
$nif = $row['nif_id'];
$flight = "SELECT flight_id FROM flights INNER JOIN clients ON flights.nif_id=clients.nif_id";
echo '<tr>';
echo '<td>'.$nif.'</td>';
echo '<td>'.$first.'</td>';
echo '<td>'.$last.'</td>';
echo '<td>'.$phone.'</td>';
echo '<td>'.$email.'</td>';
echo '<td>'.$flight.'</td>';
echo '</tr>';
}
}
?>
I need to echo the result of the SELECT flight_id FROM flights INNER JOIN clients ON flights.nif_id=clients.nif_id query. But when I save the file, what I get on the page is a link with that query instead of the result.
Should I start a new $sql = with that query under the first $sql =?
Or is there other way?
I tried UNION and SELECT *, flight_id FROM flights INNER JOIN clients ON flights.nif_id=clients.nif_id FROM clients ORDER BY nif_id ASC; but then I get mysqli_num_rows() expects parameter 1 to be mysqli_result, bool given.
You don't need two queries. Just use the joined query.
<?php
include_once '../includes/db.inc.php';
$sql = "SELECT c.prm_nome, c.apelido, c.nmr_tlm, c.mail, c.nif_id, f.flight_id
FROM clients c
JOIN flights f ON f.nif_id = c.nif_id
ORDER BY c.nif_id ASC;";
$result = mysqli_query($conn, $sql) or die(mysqli_error($conn));
$resultCheck = mysqli_num_rows($result);
if ($resultCheck > 0) {
while ($row = mysqli_fetch_assoc($result)) {
$first = $row["prm_nome"];
$last = $row["apelido"];
$phone = $row['nmr_tlm'];
$email = $row['mail'];
$nif = $row['nif_id'];
$flight = $row['flight_id'];
echo '<tr>';
echo '<td>'.$nif.'</td>';
echo '<td>'.$first.'</td>';
echo '<td>'.$last.'</td>';
echo '<td>'.$phone.'</td>';
echo '<td>'.$email.'</td>';
echo '<td>'.$flight.'</td>';
echo '</tr>';
}
}
?>

mysql query - to echo groups of products with foreach in stylable divs

hope somone can help me - I have this code:
$query = "SELECT * FROM `products` WHERE `category` = 100 AND `showme` = 1 `ORDER BY `nr` ASC";`
$result = mysql_query($query);
while($row = mysql_fetch_object($result)){
echo '<div class="'.$row->design.'">
<img src="'.$row->img.'" width="100%"><br>
<span><b>'.$row->name.'</b></span><br><span>'.$row->descr.'</span><br />
<span>'.$row->preprice.' </span><span>'.$row->price.'</span><span> '.$row->unit.'</span></div>
';
}
It displays like this: http://gartenundhof.de/gartenundhof-produkte5.php
It should look about like:http://gartenundhof.de/gartenundhof-produkte.php (which has 3 separate queries)
"SELECT * FROM 'products' ORDER BY 'category' ASC";
Try this
You can try it:
$query = "SELECT * FROM `products` WHERE `showme` = 1 `ORDER BY category,`nr` ASC";
$result = mysql_query($query);
$category = -1;
while($row = mysql_fetch_object($result)){
if($category != $row->category) {
$category = $row->category;
eho "<h2>$category</h2>";
}
echo '<div class="'.$row->design.'">
<img src="'.$row->img.'" width="100%"><br>
<span><b>'.$row->name.'</b></span><br><span>'.$row->descr.'</span><br />
<span>'.$row->preprice.' </span><span>'.$row->price.'</span><span> '.$row->unit.'</span></div>';
}
Assuming you have 2 tables Products and Categories:
$categories_query = "SELECT * FROM categories ORDER BY id ASC";
$categories = mysql_query($categories_query);
while($category = mysql_fetch_object($categories)) {
echo "Category: " . $category->name . "<br />";
$products_query = "SELECT * FROM products WHERE category_id = " . $category->id . " AND showme = 1 ORDER BY nr ASC";
while($product = mysql_fetch_object($products_query)) {
echo "Product: " . $product->name . "<br />";
}
}

I want to add the following code into a table and limit amount of entries

I have the following code on a .php page and I want to display it inside a table and only show the last 10 entries
<?php
$servername = "localhost";
$username = "";
$password = "";
$dbname = "";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT * FROM dispenses";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
echo "<br> Amount: " . $row["amount"] . " - Time Dispensed: ". $row["dispensed"] . "<br>";
}
} else {
echo "0 results";
}
$conn->close();
?>
You could store all the results in an array and subsequently display only last 10 elements of that array.
while($row = $result->fetch_assoc()) {
$results[] = $row;
}
for($i = count($results)-10; $i < count($results); $i++){
echo "<br> Amount: " . $results[$i]["amount"] . " - Time Dispensed: ". $results[$i]["dispensed"] . "<br>";
}
You can limit the number of results with LIMIT:
$sql = "SELECT * FROM dispenses LIMIT 10";
You can choose an offset as well. Check documentation for more.
p.s.: so in order to get last x entries using order by y use:
$sql = "SELECT * FROM (SELECT * FROM dispenses ".
"ORDER BY y DESC LIMIT 10) AS intermediate ORDER by y ASC";
Check this Fiddle to see how it works. I select the last three records based on id or insert date. I forgot to define an alias in the statement above. This is fixed now. Hope it helps ....

PDO Double LIKE with Params

I'm executing a query with PDO that doesn't retrieve any result via PHP but works in phpMyAdmin.
I'm sure about the connections setting as it's not the first query of my script and the other ones work fine.
Here the PHP code :
$retour = array();
$filters = array();
$filters['media_type'] = 'mytype';
$filters['libelle'] = 'sometext';
$start = 0;
$count = 9;
$sql = "SELECT * FROM ".DB_PROD_PREFIX.$this->table." t ";
$sql .= " LEFT JOIN ".DB_PROD_PREFIX.$this->table."_lang l ON t.id = l.id AND l.langue = :langue";
$sql .= " WHERE 1";
if (count($filter)>0){
foreach($filter as $field => $value){
$sql .= " AND ".$field." LIKE :".$field;
}
}
$sql .= ($order!='' ? " ORDER BY ".$order : '');
$sql .= ($count != '' ? " LIMIT ".($start != ''?':start':'0').", :count" : '');
$stmt = $db->prepare($sql);
if($start != '') $stmt->bindParam('start', $start, PDO::PARAM_INT);
if($count != '') $stmt->bindParam('count', $count, PDO::PARAM_INT);
if ($langue != '') $stmt->bindParam('langue', $langue);
if (count($filter)>0){
foreach($filter as $field => $value) {
$f = '%'.$value.'%';
$stmt->bindParam($field, $f, PDO::PARAM_STR);
}
}
echo $stmt->queryString.print_r($filter, true);
if (!$stmt->execute()) echo $stmt->errorInfo();
$res = $stmt->fetchAll();
foreach($res as $id => $row){
$retour[]=$row;
}
return $retour;
If I unset one of the 2 keys of $filter array, the query work fine.
Here is the SQL generated :
SELECT * FROM table1 t
LEFT JOIN table1_lang l ON t.id = l.id AND l.langue = :langue
WHERE 1
AND media_type LIKE :media_type
AND libelle LIKE :libelle
ORDER BY position LIMIT :start, :count
Thanks for your help!
Pierre M.
It doesn't work better but thanks for the tip!
Here is a piece of code managing the LIKE parameters that works :
$media_type = '%'.$filter['media_type'].'%';
$stmt->bindParam('media_type', $media_type, PDO::PARAM_STR);
$libelle = '%'.$filter['libelle'].'%';
$stmt->bindParam('libelle', $libelle, PDO::PARAM_STR);
Why doing the same with a foreach on the array doesn't work ?
if (count($filter)>0){
foreach($filter as $field => $value) {
$value = "%$value%";
$stmt->bindParam($field, $value, PDO::PARAM_STR);
}
}

Merge arrays in php

In the above code in each foreach loop i get a seperate array every time . I wanna combine all these array . I have tried array_merge but it is not working . Is there any other way?
Some of the results are two dimentional array
foreach ($location as $loc)
{
$query = "select name
from locations l where l.location_id = $loc";
$query = $this->db->query($query);
$data = $query->result_array();
}
Thanks in advance.
Either use array_merge():
$data = array();
foreach ($location as $loc) {
$query = "SELECT name FROM locations l WHERE l.location_id = " . $loc;
$query = $this->db->query($query);
$data = array_merge($data, $query->result_array());
}
...or merge the location id's first and then do a single query, which is much faster:
$in = implode(', ', $location);
$query = "SELECT name FROM locations l WHERE l.location_id IN (" . $in . ")";
$query = $this->db->query($query);
$data = $query->result_array();
$q = 'SELECT `name` FROM `locations` AS `l` WHERE ';
foreach ($location as $loc) {
$q .= "`l`.`location_id` = '$loc' OR ";
}
$q = rtrim($q, 'OR ');
$query = $this->db->query($q);
$data = $query->result_array();