Compare uploaded data in database and raw CSV data - php

Here is the code after I uploaded the raw file then tried to validate the raw file with the uploaded file to see if they match:
while ($db_fetch_row = sqlsrv_fetch_array($database_query)){
$db_eid = $db_fetch_row['eid'];
$db_team_lead = $db_fetch_row['team_lead'];
$db_role = $db_fetch_row['role'];
$db_productivity = $db_fetch_row['productivity'];
$db_quality = $db_fetch_row['quality'];
$db_assessment = $db_fetch_row['assessment'];
$db_staffed_hours = $db_fetch_row['staffed_hours'];
$db_kpi_productivity = $db_fetch_row['kpi_productivity'];
$db_kpi_quality = $db_fetch_row['kpi_quality'];
$db_kpi_assessment = $db_fetch_row['kpi_assessment'];
$db_kpi_staffed_hours = $db_fetch_row['kpi_staffed_hours'];
for($row = 2; $row <= $lastRow; $row++) {
$eid = $worksheet->getCell('A'.$row)->getValue();
$team_lead = $worksheet->getCell('C'.$row)->getValue();
$role = $worksheet->getCell('B'.$row)->getValue();
$productivity = $worksheet->getCell('D'.$row)->getValue();
$productivity1 = chop($productivity,"%");
$quality = $worksheet->getCell('E'.$row)->getValue();
$quality1 = chop($quality,"%");
$assessment = $worksheet->getCell('F'.$row)->getValue();
$assessment1 = chop($assessment,"%");
$staffed_hours = $worksheet->getCell('G'.$row)->getValue();
$staffed_hours1 = chop($staffed_hours,"%");
$kpi_productivity = $worksheet->getCell('H'.$row)->getValue();
$kpi_quality = $worksheet->getCell('I'.$row)->getValue();
$kpi_assessment = $worksheet->getCell('J'.$row)->getValue();
$kpi_staffed_hours = $worksheet->getCell('K'.$row)->getValue();
if($db_eid == $eid) {
echo "Raw and Uploaded file Matched";
} else {
echo "Did not match";
}
}
}
The output always didn't match, as you can see below:

Of course it outputs that. Let's think it through:
For every row in the DB, you are checking EVERY row in the CSV. Presumably there is only ONE row in the CSV that has the same ID as the row in the DB, so that means if there are 100 records in the CSV, it will output "no match" 99 times (assuming there is 1 record in the CSV that does match).
One approach is to separate it into a function and attempt to find the matching row, as follows:
// Loop over all DB records
while ($db_fetch_row = sqlsrv_fetch_array($database_query)) {
// call our new function to attempt to find a match
$match = find_matching_row( $db_fetch_row, $worksheet );
// If there's no match, output "didn't find a match"
if ( ! $match ) {
echo '<br>DID NOT FIND A MATCH.';
// If there IS a match, $match represents the row number to use....
} else {
var_dump( $match );
// Do your work on the match data...
$team_lead = $worksheet->getCell('C'.$match)->getValue();
// ...etc
}
}
/**
* Attempt to find a row from the CSV with the same ID as the DB
* record passed in.
*
* #param array $db_fetch_row
* #param mixed $worksheet
*/
function find_matching_row( $db_fetch_row, $worksheet ) {
$db_eid = $db_fetch_row['eid'];
// Youll need to calculate $lastRow for this to work right..
$lastRow = .... ;
// Loop through the CSV records
for($row = 2; $row <= $lastRow; $row++) {
// If the IDs match, return the row number
if($db_eid == $worksheet->getCell('A'.$row)->getValue() ){
return $row;
}
}
// If no match, return FALSE
return FALSE;
}

Related

PHP for loop with Database and API Data only calculates 1 result

I try to loop trough a php script to calculate a Total Holding of a Persons Portfolio. But my code only puts out one calculated field instead of all from the Database.
My DB looks like this:
id email amount currency date_when_bought price_when_bought
33 test#test.com 100 BTC 2019-04-17 4000
34 test#test.com 50 ETH 2019-04-17 150
My Code (pretty messy)
<?php
include('databasecon.php');
//// GET API JSON DATA
$coinData = json_decode(file_get_contents('https://min-api.cryptocompare.com/data/pricemultifull?fsyms=BTC,ETH,XRB,IOTA,XRP,XLM,TRX,LINK,USDT&tsyms=USD'), true);
//SELECT ALL MAIL
$result = mysqli_query($con, "SELECT DISTINCT email FROM user_data");
$email_array = array();
while($row = mysqli_fetch_array($result))
{
$email_array[] = $row['email'];
};
// PORTFOLIO ARRAYS
for ($i = 0; $i < sizeof($email_array); $i++) {
$sql = mysqli_query($con, "SELECT DISTINCT * FROM crypto_data WHERE email = '$email_array[$i]'");
while($row = mysqli_fetch_array($sql)){
$myCoins[$row['currency']] = array('balance' => $row['amount'],
'boughtprice' => $row['price_when_bought']);
};
// 0 VALUES FOR CALCULATION
$portfolioValue = 0;
$totalNET = 0;
$Value24H = 0;
// information in json path ['RAW'] so safeguard here to be sure it exists
if (isset($coinData['RAW'])) {
// then loop on all entries $cryptoSymbol will contain for example BTC and cryptoInfo the array USD => [...]
foreach($coinData['RAW'] as $cryptoSymbol => $cryptoInfo) {
// safeguard, check path [USD][FROMSYMBOL] exists
if (!isset($cryptoInfo['USD']) || !isset($cryptoInfo['USD']['FROMSYMBOL'])) {
// log or do whatever to handle error here
echo "no path [USD][FROMSYMBOL] found for crypto: " . $cryptoSymbol . PHP_EOL;
continue;
}
// Symbol in on your json path/array [USD][FROMSYMBOL]
$thisCoinSymbol = $cryptoInfo['USD']['FROMSYMBOL'];
$coinHeld = array_key_exists($thisCoinSymbol, $myCoins);
// Only retour held
if ( !$coinHeld ) { continue; }
// get price:
$thisCoinPrice = $cryptoInfo['USD']['PRICE'];
// get symbol holding:
if ($coinHeld) {
$myBalance_units = $myCoins[$thisCoinSymbol]['balance'];
};
// calculate total holdings:
if ($coinHeld) {
$myBalance_USD = $myBalance_units * $thisCoinPrice;
$portfolioValue += $myBalance_USD;
};
echo '<br>';
echo $email_array[$i];
echo $portfolioValue . PHP_EOL;
echo '<br>';
echo '<br>';
$myCoins = null;
}}};
?>
The Steps are:
1 API connection
2 Select Mail adresses from user_data and put them into an Array
3 start for-loop with size of the email_array
4 Query the crypto_data DB to get all results from that mail
5 Put all Data from crypto_data into Array
6 foreach loop the API
7 Calculations
8 Echo the results
9 null $myCoins
As a result, I get the right Mail Adress + the second row (id 33) calculated with the actual price. But my Result should also plus count id 33 and 34 to get the total result.
To clearify, I get "100 * Price of BTC" , but I need "100 * Price of BTC + 50 * Price of ETH"
Somehow my code only puts out 1 row, but does not calculate them like I want to do so here:
// calculate total holdings:
if ($coinHeld) {
$myBalance_USD = $myBalance_units * $thisCoinPrice;
$portfolioValue += $myBalance_USD;
};
Any help is appreciated, thank you very much.
There are few bugs in your code, such as:
You are setting $myCoins to null immediately after the first iteration of foreach loop, so array_key_exists() function will fail in the next iteration. Remove it entirely, there's no need of setting $myCoins to null.
Keep the below just inside the outer for loop. You should not print the portfolio value for each iteration of foreach loop, rather print the aggregated portfolio value for each email address.
echo '<br>';
echo $email_array[$i];
echo $portfolioValue . PHP_EOL;
echo '<br>';
echo '<br>';
Reset $portfolioValue value to 0 at the end of the for loop.
So your code should be like this:
<?php
include('databasecon.php');
// GET API JSON DATA
$coinData = json_decode(file_get_contents('https://min-api.cryptocompare.com/data/pricemultifull?fsyms=BTC,ETH,XRB,IOTA,XRP,XLM,TRX,LINK,USDT&tsyms=USD'), true);
//SELECT ALL MAIL
$result = mysqli_query($con, "SELECT DISTINCT email FROM user_data");
$email_array = array();
while($row = mysqli_fetch_array($result)){
$email_array[] = $row['email'];
}
// PORTFOLIO ARRAYS
for ($i = 0; $i < sizeof($email_array); $i++) {
$sql = mysqli_query($con, "SELECT DISTINCT * FROM crypto_data WHERE email = '$email_array[$i]'");
while($row = mysqli_fetch_array($sql)){
$myCoins[$row['currency']] = array('balance' => $row['amount'], 'boughtprice' => $row['price_when_bought']);
}
// 0 VALUES FOR CALCULATION
$portfolioValue = 0;
$totalNET = 0;
$Value24H = 0;
// information in json path ['RAW'] so safeguard here to be sure it exists
if (isset($coinData['RAW'])) {
// then loop on all entries $cryptoSymbol will contain for example BTC and cryptoInfo the array USD => [...]
foreach($coinData['RAW'] as $cryptoSymbol => $cryptoInfo) {
// safeguard, check path [USD][FROMSYMBOL] exists
if (!isset($cryptoInfo['USD']) || !isset($cryptoInfo['USD']['FROMSYMBOL'])) {
// log or do whatever to handle error here
echo "no path [USD][FROMSYMBOL] found for crypto: " . $cryptoSymbol . PHP_EOL;
continue;
}
// Symbol in on your json path/array [USD][FROMSYMBOL]
$thisCoinSymbol = $cryptoInfo['USD']['FROMSYMBOL'];
$coinHeld = array_key_exists($thisCoinSymbol, $myCoins);
// Only retour held
if ( !$coinHeld ) { continue; }
// get price:
$thisCoinPrice = $cryptoInfo['USD']['PRICE'];
// get symbol holding:
if ($coinHeld) {
$myBalance_units = $myCoins[$thisCoinSymbol]['balance'];
}
// calculate total holdings:
if ($coinHeld) {
$myBalance_USD = $myBalance_units * $thisCoinPrice;
$portfolioValue += $myBalance_USD;
}
}
}
echo '<br>';
echo $email_array[$i];
echo $portfolioValue . PHP_EOL;
echo '<br>';
echo '<br>';
$portfolioValue = 0;
}
?>
Sidenote: Learn about prepared statement because right now your query is susceptible to SQL injection attack. Also see how you can prevent SQL injection in PHP.

Minimize efforts with foreach

I'm trying to build a script that will download users from a db table and attach a new random IP to each user based on his state.
The problem is that I wrote a lot of code and there is still much Copy/Paste job to be done if I keep it with this approach.
Can someone point me to the right direction on how to properly do that?
So first I have 50 of these:
$California_Text = file_get_contents('state/California.txt');
$California_textArray = explode("\n", $California_Text);
$Idaho_Text = file_get_contents('state/Idaho.txt');
$Idaho_textArray = explode("\n", $Idaho_Text);
$Illinois_Text = file_get_contents('state/Illinois.txt');
$Illinois_textArray = explode("\n", $Illinois_Text);
$Indiana_Text = file_get_contents('state/Illinois.txt');
$Indiana_textArray = explode("\n", $Indiana_Text);
$Iowa_Text = file_get_contents('state/Iowa.txt');
Then I have 50 of these:
while($row = $result->fetch_assoc()) {
if (isset($row["state"])) {
foreach ($row as $value){
$California_randArrayIndexNum = array_rand($California_textArray);
$p_California = $California_textArray[$California_randArrayIndexNum];
$Texas_randArrayIndexNum = array_rand($Texas_textArray);
$p_Texas = $Texas_textArray[$Texas_randArrayIndexNum];
$Alabama_randArrayIndexNum = array_rand($Alabama_textArray);
$p_Alabama = $Alabama_textArray[$Alabama_randArrayIndexNum];
$Alaska_randArrayIndexNum = array_rand($Alaska_textArray);
$p_Alaska = $Texas_textArray[$Alaska_randArrayIndexNum];
$Arizona_randArrayIndexNum = array_rand($Arizona_textArray);
$p_Arizona = $California_textArray[$Arizona_randArrayIndexNum];
.....
Then I have 50 of these:
if ($row["state"] == "california") {
$stateip = $p_California;
}
else if ($row["state"] == "texas") {
$stateip = $p_Texas;
}
else if ($row["state"] == "alabama") {
$stateip = $p_Alabama;
}
else if ($row["state"] == "alaska") {
$stateip = $p_Alaska;
}
I'm pretty much sure that it's a bad approach.. Maybe there's a way to do all this with like 3 lines of foreach?
Something like this:
// holds your content
$state_content = [];
while($row = $result->fetch_assoc()) {
// check do we have state set
if (!empty($row["state"])) {
$stateip = getStateIpByName($row["state"]);
}
}
/**
* Returns random IP
*/
function getStateIpByName($state_name) {
$content = getStateContent($state_name);
return $content[array_rand($content)];
}
/**
* Returns your's state content by state name
*/
function getStateContent($state_name) {
// checks do we already have content for this state
if(!isset($state_content[$state_name])) {
// generate file name
$file_name = "state/";
$file_name .= str_replace(" ", "", ucwords($state_name));
$file_name .= ".txt";
$state_text = file_get_contents($file_name);
$state_content[$state_name] = explode("\n", $state_text);
}
return $state_content[$state_name];
}
There are probably some errors but you will get idea.
Store all states in an array and do all operations within a foreach block
$states=['california',..];
foreach($states as $state){
//Your code for one state
//Replace state name with $state variable
}

php code of troubling getting multiple value

I have codes that should be getting value from mysql database, I can get only one value but I have while loop so it can get value and output data separated with comma. But I only get one value and cannot get multiple value. the result should be like this, // End main PHP block. Data looks like this: [ [123456789, 20.9],[1234654321, 22.1] ] here is the code:
<?php
// connect to MySQL
mysql_connect('localhost','','') or die("Can't connect that way!");
#mysql_select_db('temperature1') or die("Unable to select a database called 'temperature'");
if(ISSET($_GET['t']) && (is_numeric($_GET['t'])) ){
// message from the Arduino
$temp = $_GET['t'];
$qry = "INSERT INTO tempArray(timing,temp) VALUES(".time().",'$temp')";
echo $qry;
mysql_query($qry);
mysql_close();
exit('200');
}
// no temp reading has been passed, lets show the chart.
$daysec = 60*60*24; //86,400
$daynow = time();
if(!$_GET['d'] || !is_numeric($_GET['d'])){
$dayoffset = 1;
} else {
$dayoffset = $_GET['d'];
}
$dlimit = $daynow-($daysec*$dayoffset);
$qryd = "SELECT id, timing, temp FROM tempArray WHERE timing>='$dlimit' ORDER BY id ASC LIMIT 1008";
// 1008 is a weeks worth of data,
// assuming 10 min intervals
$r = mysql_query($qryd);
$count = mysql_num_rows($r);
$i=0;
$r = mysql_query($qryd);
$count = mysql_num_rows($r);
while($row=mysql_fetch_array($r, MYSQL_ASSOC)) {
$tid=$row['id'];
$dt = ($row['timing']+36000)*1000;
$te = $row['temp'];
if($te>$maxtemp) $maxtemp=$te; // so the graph doesnt run along the top
if($te<$mintemp) $mintemp=$te; // or bottom of the axis
$return="[$dt, $te]";
echo $return; //here I get all values [1385435831000, 21][1385435862000, 23][1385435892000, 22][1385435923000, 25][1385435923000, 22]
$i++;
if($i<$count) $return= ","; echo $return; // if there is more data, add a ',' however, it return me ,,,[1385435923000, 22]
$latest = "$dt|$te"; // this will get filled up with each one
}
mysql_close();
// convert $latest to actual date - easier to do it here than in javascript (which I loathe)
$latest = explode('|',$latest);
$latest[0] = date('g:ia, j.m.Y',(($latest[0])/1000)-36000);
?>
You're just assigning $return to the values from the last row your while loop grabbed instead of concatenating it. Try this
$return = "[";
while($row=mysql_fetch_array($r, MYSQL_ASSOC)) {
$tid=$row['id'];
$dt = ($row['timing']+36000)*1000;
$te = $row['temp'];
if($te>$maxtemp) $maxtemp=$te; // so the graph doesnt run along the top
if($te<$mintemp) $mintemp=$te; // or bottom of the axis
$return.="[$dt, $te]";
$i++;
if($i<$count) $return .= ", ";// if there is more data, add a ','
$latest = "$dt|$te"; // this will get filled up with each one
}
$return .= "]";

Voting Duplicate Votes

We currently have a voting system setup that saves the IP address of the person making a vote to stop duplicate votes.
However everyday the IP address is removed from the database so they can re-vote on there favourite item.
Looking through the code below can you see how I can stop this so that a person with a certain IP address can never vote for that certain item again? They are however able to vote on the other entrants, but again only vote once.
Any ideas?
<?php
// Script Voting - http://www.coursesweb.net/
class Voting {
// properties
static protected $conn = false; // stores the connection to mysql
public $affected_rows = 0; // number of affected, or returned rows in SQL query
protected $voter = ''; // the user who vote, or its IP
protected $nrvot = 0; // if it is 1, the user can vote only one item in a day, 0 for multiple items
protected $svoting = 'mysql'; // 'mysql' to register data in database, any other value register in TXT files
public $votitems = 'voting'; // Table /or file_name to store items that are voted
public $votusers = 'votusers'; // Table /or filename that stores the users who voted in current day
protected $tdy; // will store the number of current day
public $eror = false; // to store and check for errors
// constructor
public function __construct() {
// sets $nrvot, $svoting, $voter, and $tdy properties
if(defined('NRVOT')) $this->nrvot = NRVOT;
if(defined('SVOTING')) $this->svoting = SVOTING;
if(defined('USRVOTE') && USRVOTE === 0) { if(defined('VOTER')) $this->voter = VOTER; }
else $this->voter = $_SERVER['REMOTE_ADDR'];
$this->tdy = date('j');
// if set to use TXT files, set the path and name of the files
if($this->svoting != 'mysql') {
$this->votitems = '../votingtxt/'.$this->votitems.'.txt';
$this->votusers = '../votingtxt/'.$this->votusers.'.txt';
}
}
// for connecting to mysql
protected function setConn() {
try {
// Connect and create the PDO object
self::$conn = new PDO("mysql:host=".DBHOST."; dbname=".DBNAME, DBUSER, DBPASS);
// Sets to handle the errors in the ERRMODE_EXCEPTION mode
self::$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
self::$conn->exec('SET CHARACTER SET utf8'); // Sets encoding UTF-8
}
catch(PDOException $e) {
$this->eror = 'Unable to connect to MySQL: '. $e->getMessage();
}
}
// Performs SQL queries
public function sqlExecute($sql) {
if(self::$conn===false OR self::$conn===NULL) $this->setConn(); // sets the connection to mysql
$re = true; // the value to be returned
// if there is a connection set ($conn property not false)
if(self::$conn !== false) {
// gets the first word in $sql, to determine whenb SELECT query
$ar_mode = explode(' ', trim($sql), 2);
$mode = strtolower($ar_mode[0]);
// performs the query and get returned data
try {
if($sqlprep = self::$conn->prepare($sql)) {
// execute query
if($sqlprep->execute()) {
// if $mode is 'select', gets the result_set to return
if($mode == 'select') {
$re = array();
// if fetch() returns at least one row (not false), adds the rows in $re for return
if(($row = $sqlprep->fetch(PDO::FETCH_ASSOC)) !== false){
do {
// check each column if it has numeric value, to convert it from "string"
foreach($row AS $k=>$v) {
if(is_numeric($v)) $row[$k] = $v + 0;
}
$re[] = $row;
}
while($row = $sqlprep->fetch(PDO::FETCH_ASSOC));
}
$this->affected_rows = count($re); // number of returned rows
}
}
else $this->eror = 'Cannot execute the sql query';
}
else {
$eror = self::$conn->errorInfo();
$this->eror = 'Error: '. $eror[2];
}
}
catch(PDOException $e) {
$this->eror = $e->getMessage();
}
}
// sets to return false in case of error
if($this->eror !== false) { echo $this->eror; $re = false; }
return $re;
}
// returns JSON string with item:['vote', 'nvotes', renot] for each element in $items array
public function getVoting($items, $vote = '') {
$votstdy = $this->votstdyCo($items); // gets from Cookie array with items voted by the user today
// if $vote not empty, perform to register the vote, $items contains one item to vote
if(!empty($vote)) {
// if $voter empty means user not loged
if($this->voter === '') return "alert('Vote Not registered.\\nYou must be logged in to can vote')";
else {
// gets array with items voted today from mysql, or txt-files (according to $svoting), and merge unique to $votstdy
if($this->svoting == 'mysql') {
$votstdy = array_unique(array_merge($votstdy, $this->votstdyDb()));
}
else {
$all_votstdy = $this->votstdyTxt(); // get 2 array: 'all'-rows voted today, 'day'-items by voter today
$votstdy = array_unique(array_merge($votstdy, $all_votstdy[$this->tdy]));
}
// if already voted, add in cookie, returns JSON from which JS alert message and will reload the page
// else, accesses the method to add the new vote, in mysql or TXT file
if(in_array($items[0], $votstdy) || ($this->nrvot === 1 && count($votstdy) > 0)) {
$votstdy[] = $items[0];
setcookie("votings", implode(',', array_unique($votstdy)), strtotime('tomorrow'));
return '{"'.$items[0].'":[0,0,3]}';
}
else if($this->svoting == 'mysql') $this->setVotDb($items, $vote, $votstdy); // add the new vote in mysql
else $this->setVotTxt($items, $vote, $all_votstdy); // add the new vote, and voter in TXT files
array_push($votstdy, $items[0]); // adds curent item as voted
}
}
// if $nrvot is 1, and $votstdy has item, set $setvoted=1 (user already voted today)
// else, user can vote multiple items, after Select is checked if already voted the existend $item
$setvoted = ($this->nrvot === 1 && count($votstdy) > 0) ? 1 : 0;
// get array with items and their votings from mysql or TXT file
$votitems = ($this->svoting == 'mysql') ? $this->getVotDb($items, $votstdy, $setvoted) : $this->getVotTxt($items, $votstdy, $setvoted);
return json_encode($votitems);
}
// insert /update rating item in #votitems, delete rows in $votusers which are not from today, insert $voter in $votusers
protected function setVotDb($items, $vote, $votstdy) {
$this->sqlExecute("INSERT INTO `$this->votitems` (`item`, `vote`) VALUES ('".$items[0]."', $vote) ON DUPLICATE KEY UPDATE `vote`=`vote`+$vote, `nvotes`=`nvotes`+1");
$this->sqlExecute("DELETE FROM `$this->votusers` WHERE `day`!=$this->tdy");
$this->sqlExecute("INSERT INTO `$this->votusers` (`day`, `voter`, `item`) VALUES ($this->tdy, '$this->voter', '".$items[0]."')");
// add curent voted item to the others today, and save them as string ',' in cookie (till the end of day)
$votstdy[] = $items[0];
setcookie("votings", implode(',', array_unique($votstdy)), strtotime('tomorrow'));
}
// select 'vote' and 'nvotes' of each element in $items, $votstdy stores items voted by the user today
// returns array with item:['vote', 'nvotes', renot] for each element in $items array
protected function getVotDb($items, $votstdy, $setvoted) {
$re = array_fill_keys($items, array(0,0,$setvoted)); // makes each value of $items as key with an array(0,0,0)
function addSlhs($elm){return "'".$elm."'";} // function to be used in array_map(), adds "'" to each $elm
$resql = $this->sqlExecute("SELECT * FROM `$this->votitems` WHERE `item` IN(".implode(',', array_map('addSlhs', $items)).")");
if($this->affected_rows > 0) {
for($i=0; $i<$this->affected_rows; $i++) {
$voted = in_array($resql[$i]['item'], $votstdy) ? $setvoted + 1 : $setvoted; // add 1 if the item was voted by the user today
$re[$resql[$i]['item']] = array($resql[$i]['vote'], $resql[$i]['nvotes'], $voted);
}
}
return $re;
}
// add /update rating item in TXT file, keep rows from today in $votusers, and add new row with $voter
protected function setVotTxt($items, $vote, $all_votstdy) {
// get the rows from file with items, if exists
if(file_exists($this->votitems)) {
$rows = file($this->votitems, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$nrrows = count($rows);
// if exist rows registered, get array for each row, with - item^vote^nvotes
// if row with item, update it and stop, else, add the row at the end
if($nrrows > 0) {
for($i=0; $i<$nrrows; $i++) {
$row = explode('^', $rows[$i]);
if($row[0] == $items[0]) {
$rows[$i] = $items[0].'^'.($row[1] + $vote).'^'.($row[2] + 1);
$rowup = 1; break;
}
}
}
}
if(!isset($rowup)) $rows[] = $items[0].'^'.$vote.'^1';
file_put_contents($this->votitems, implode(PHP_EOL, $rows)); // save the items in file
// add row with curent item voted and the voter (today^voter^item), and save all the rows
$all_votstdy['all'][] = $this->tdy.'^'.$this->voter.'^'.$items[0];
file_put_contents($this->votusers, implode(PHP_EOL, $all_votstdy['all']));
// add curent voted item to the others today, and save them as string ',' in cookie (till the end of day)
$all_votstdy[$this->tdy][] = $items[0];
setcookie("votings", implode(',', array_unique($all_votstdy[$this->tdy])), strtotime('tomorrow'));
}
// get from TXT 'vote' and 'nvotes' of each element in $items, $votstdy stores items voted by the user today
// returns array with item:['vote', 'nvotes', renot] for each element in $items array
protected function getVotTxt($items, $votstdy, $setvoted) {
$re = array_fill_keys($items, array(0,0,$setvoted)); // makes each value of $items as key with an array(0,0,0)
if(file_exists($this->votitems)) {
$rows = file($this->votitems, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$nrrows = count($rows);
// if exist rows registered, get array for each row, with - item^vote^nvotes
// if row with item is in $items, add its data in $re
if($nrrows > 0) {
for($i=0; $i<$nrrows; $i++) {
$row = explode('^', $rows[$i]);
$voted = in_array($row[0], $votstdy) ? $setvoted + 1 : $setvoted; // add 1 if the item was voted by the user today
if(in_array($row[0], $items)) $re[$row[0]] = array($row[1], $row[2], $voted);
}
}
}
return $re;
}
// gets and returns from Cookie an array with items voted by the user ($voter) today
protected function votstdyCo() {
$votstdy = array();
// if exists cookie 'votings', adds items voted today in $votstdy (array_filter() - removes null, empty elements)
if(isset($_COOKIE['votings'])) {
$votstdy = array_filter(explode(',', $_COOKIE['votings'])); // cookie stores string with: item1, item2, ...
}
return $votstdy;
}
// returns from mysql an array with items voted by the user today
protected function votstdyDb() {
$votstdy = array();
$resql = $this->sqlExecute("SELECT `item` FROM `$this->votusers` WHERE `day`=$this->tdy AND `voter`='$this->voter'");
if($this->affected_rows > 0) {
for($i=0; $i<$this->affected_rows; $i++) {
$votstdy[] = $resql[$i]['item'];
}
}
return $votstdy;
}
// returns from TXT file an array with 2 arrays: all rows voted today, and items voted by the user today
protected function votstdyTxt() {
$re['all'] = array(); $re[$this->tdy] = array();
if(file_exists($this->votusers)) {
$rows = file($this->votusers, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$nrrows = count($rows);
// if exist rows registered, get array for each row, with - day^voter^item , compare 'day', and 'voter'
if($nrrows > 0) {
for($i=0; $i<$nrrows; $i++) {
$row = explode('^', $rows[$i]);
if($row[0] == $this->tdy) {
$re['all'][] = $rows[$i];
if($row[1] == $this->voter) $re[$this->tdy][] = $row[2];
}
}
}
}
return $re;
}
}
Make an SQL database of the IP addresses you want to ban, or if the list is short enough us an array.
Check if the IP address is in the database or array. If it's not allow them to vote. However, if it is let them think they voted put it in the database and make it as voted, but mark the vote as does not count so they will not try to get around your block.
This function seems to be deleting votes that are not from "today":
// insert /update rating item in #votitems, delete rows in $votusers which are not from today, insert $voter in $votusers
protected function setVotDb($items, $vote, $votstdy) {
$this->sqlExecute("INSERT INTO `$this->votitems` (`item`, `vote`) VALUES ('".$items[0]."', $vote) ON DUPLICATE KEY UPDATE `vote`=`vote`+$vote, `nvotes`=`nvotes`+1");
//$this->sqlExecute("DELETE FROM `$this->votusers` WHERE `day`!=$this->tdy");
$this->sqlExecute("INSERT INTO `$this->votusers` (`day`, `voter`, `item`) VALUES ($this->tdy, '$this->voter', '".$items[0]."')");
// add curent voted item to the others today, and save them as string ',' in cookie (till the end of day)
$votstdy[] = $items[0];
setcookie("votings", implode(',', array_unique($votstdy)), strtotime('tomorrow'));
}
I've commented out the delete query. You should test it out before putting it into production.
Your database structure seems a bit confusing, you have a table to count the vote per items and a table to count the vote per user.
You should review your database structure to merge those two tables in one table, with the : item, user, vote fields.
So you could keep a record for each vote of each user for each item as long as you want and eventualy make count() or sum() requests to get the total of votes per item

PHP/MySQL Printing Duplicate Labels

Using an addon of FPDF, I am printing labels using PHP/MySQL (http://www.fpdf.de/downloads/addons/29/). I'd like to be able to have the user select how many labels to print. For example, if the query puts out 10 records and the user wants to print 3 labels for each record, it prints them all in one set. 1,1,1,2,2,2,3,3,3...etc. Any ideas?
<?php
require_once('auth.php');
require_once('../config.php');
require_once('../connect.php');
require('pdf/PDF_Label.php');
$sql="SELECT $tbl_members.lastname, $tbl_members.firstname,
$tbl_members.username, $tbl_items.username, $tbl_items.itemname
FROM $tbl_members, $tbl_items
WHERE $tbl_members.username = $tbl_items.username";
$result=mysql_query($sql);
if(mysql_num_rows($result) == 0){
echo "Your search criteria does not return any results, please try again.";
exit();
}
$pdf = new PDF_Label("5160");
$pdf->AddPage();
// Print labels
while($rows=mysql_fetch_array($result)){
$name = $rows['lastname'].', '.$rows['firstname';
$item= $rows['itemname'];
$text = sprintf(" * %s *\n %s\n", $name, $item);
$pdf->Add_Label($text);
}
$pdf->Output('labels.pdf', 'D');
?>
Assuming that a variable like $copies is an integer of how many copies they want made, I would make the following modification:
// Print labels
while( $row = mysql_fetch_array( $result ) ){
// Run Once for Each Result
$name = $row['lastname'].', '.$row['firstname'];
$item = $row['itemname'];
$text = sprintf(" * %s *\n %s\n", $name, $item);
if( isset( $copies ) ) {
// The Copies Variable exists
for( $i=0 ; $i<$copies ; $i++ ) {
// Run X times - Once for each Copy
$pdf->Add_Label($text);
}
} else {
// The Copies Variable does not exist - Assume 1 Copy
$pdf->Add_Label($text);
}
}
This should provide the required functionality.

Categories