Why isn't my fread working? - php

Together is a program that is meant to look into a "csv" file with holidays in it, allow someone to choose a button labeled a number, and then write to file the holiday randomly chosen. It isn't working. Any help? Specifically the "choose.php" isn't working and isn't recieving any errors when I enable the ini_set settings, etc.
HTML FILE:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
function start(){
$.ajax({
url:"cgi-bin/php/holiday/start.php",
success:function(code){
$("div#content").html(code);
}
});
}
function choose(link){
var data_id = $(link).attr('rel');
var post = {
id : data_id
}
$.ajax({
url:"cgi-bin/php/holiday/choose.php",
data:post,
method:"POST",
success:function(code){
$("div#content").html(code);
}
});
}
$(document).ready(function(){
start();
});
</script>
</head>
<body>
<header id='header'></header>
<div id='content'></div>
<div id='footer'></div>
</body>
</html>
start.php
<?php
$row = 1;
if (($handle = fopen("csv/index.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p>There are {$num} choices left</p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
?><button onClick='choose(this);' class='choice' rel='<?php echo $c;?>'><?php echo $c;?></div><?php
}
}
fclose($handle);
}?>
choose.php
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$file = fopen("csv/index.csv","r");
$holidays = explode(',',fread($file));
fclose($file);
shuffle($holidays);
$file = fopen("csv/choices.csv","a");
$holiday = $holidays[$_GET['rel']];
fwrite($file, "MY NAME GOT " . {$holiday});
fclose($file);
unset($holidays[$_POST['rel']]);
$file = fopen("csv/index.csv","w");
fwrite($file,implode(",",$holidays);
fclose($file);
echo "YOU GOT {$holiday}";
?>
csv/index.php
christmas,chinese new year
csv/choices is empty

fread() requires a second argument, the number of bytes to read. If you want to read the whole file, you can use the filesize() function:
$holidays = explode(',',fread($file, filesize($file)));
But if you want to read an entire file, you can use file_get_contents().
$holidays = explode(',', file_get_contents("csv/index.csv"));
And you can rewrite the file with:
file_put_contents("csv/index.csv", implode(',', $holidays));

Related

Asynchronus-PHP Upload Huge csv data into MYSQL

I tried to upload around 20k rows CSV into SQL using async method referring to this post :
How to import a huge CSV file with 200,00 rows to MySQL (asynchronous and fast)?
The script already running and success when I upload 10000 data, but when I checked into the database, I found that only half rows (5000 rows) were Inserted.
I've tried to change the $batchsize from 1000 to 100, only 9400rows inserted instead of supposedly 10000 rows
here's my current code :
index.php :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>csv upload</title>
</head>
<body>
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="csv" value="" />
<input type="submit" name="submit" value="Save" />
</form>
</body>
</html>
upload.php :
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.js"></script>
<script>
//Declaration of function that will insert data into database
function senddata(filename){
var file = filename;
$.ajax({
type: "POST",
url: "senddata.php",
data: {file},
async: true,
success: function(html){
$("#result").html(html);
}
})
}
</script>
<?php
$batchsize = 100; //split huge CSV file by 1,000, you can modify this based on your needs
if($_FILES['csv']['error'] == 0){
$name = $_FILES['csv']['name'];
$ext = explode(".", $name);
$ext = $ext[1];
$tmpName = $_FILES['csv']['tmp_name'];
if($ext === 'csv'){ //check if uploaded file is of CSV format
if(($handle = fopen($tmpName, 'r')) !== FALSE) {
set_time_limit(0);
$row = 0;
while(($data = fgetcsv($handle)) !== FALSE) {
//splitting of CSV file :
if ($row % $batchsize == 0):
$file = fopen("minpoints$row.csv","w");
endif;
$csv[$row]['col1'] = $data[0];
$csv[$row]['col2'] = $data[1];
$min = $data[0];
$points = $data[1];
$json = "'$min', '$points'";
fwrite($file,$json.PHP_EOL);
//sending the splitted CSV files, batch by batch...
if ($row % $batchsize == 0):
echo "<script> senddata('minpoints$row.csv'); </script>";
endif;
$row++;
}
fclose($file);
fclose($handle);
}
} else {
echo "Only CSV files are allowed.";
}
//alert once done.
echo "<script> alert('CSV imported!') </script>";
} ?>
senddata.php :
<?php
include('config.php');
$data = $_POST['file'];
$handle = fopen($data, "r");
$test = file_get_contents($data);
// print_r($test);die;
if ($handle) {
$counter = 0;
//instead of executing query one by one,
//let us prepare 1 SQL query that will insert all values from the batch
$sql ="INSERT INTO table_test(name,contact_number) VALUES ";
while (($line = fgets($handle)) !== false) {
$sql .= "($line),";
$counter++;
}
$sql = substr($sql, 0, strlen($sql) - 1);
if ($conn->query($sql) === TRUE) {
} else {
}
fclose($handle);
} else {
}
//unlink CSV file once already imported to DB to clear directory
unlink($data);
?>
My Goals are :
Upload huge csv data asynchronusly with complete data
To understand this codes :
--> fwrite($file,$json.PHP_EOL); and
--> senddata('minpoints$row.csv'); ;
The table table_test has an NOT NULL column and the csv has NULL values at some case and that's why is not inserted.
You can make name and contact_number NULL, with
ALTER TABLE table_test MODIFY name your-type(your-number); Columns are nullable by default. As long as the column is not declared UNIQUE or NOT NULL, there shouldn't be any problems.
#owf: - thank you, after i changed the structure table, it works
perfectly. Anyway do you have an idea how to skip the first row
(header) ? I've tried to use IF the $counter > 0 on senddata.php , but
it skips every first counter of each batch
R:
First for all, you need to $flag the first parsed csv to know that it comes with the first row to be skipped.
Add a variable to the ajax that check if is the first csv registered.
So, en ajax.php you know if the csv is the first one or not, based in this method, you can skip the first row of the first batched csv
using this you can skip the just first row of CSV file (header of CSV file) . try that
while (($line = fgets($handle)) !== false) {
if ($_POST['file'] == 'minpoints0.csv' && $counter > 0) {
$sql .= "('$line'),";
}
$counter++;
}

Animation on CSV array changes

I have a simple page that displays race results. The results are pulled from a CSV file which updates upon completion of each race. The changes could be subtle so would like to have an animation, fade in/out or colour change etc, only if results are different. I want to add a to the table ONLY if the CSV file has new results as a visual aid to the update.
EDIT: I am unsure where to start on implementation so no code is reflected below. The CSV is scanned every 1 second and table updated. The outcome I want is for the table results to have an animation if/when array results change, else no animation.
EDIT 2: I have attempted to output the current racer number from the results data ($csv[1]) to a file and then check that against the current race number but it doesn't seem to work. When I pull $lastrace[0] and $csv[1] they are always the same number. I thought having it higher in the PHP would get $lastrace before writing the new number but doesn't appear so.
// Get Racer No from previous race
$lastrace = str_getcsv(file_get_contents('lastraceno.txt'));
// Puts current racer no to CSV file
$file = fopen("lastraceno.txt","w");
fputcsv($file,explode(',',$csv[1]));
fclose($file);
My code as it stands is as below - have trimmed some irrelevant code.
index.php
<head>
<script src="jquery-2.1.3.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
refreshTable();
});
function refreshTable(){
$('#tableHolder').load('table.php', function(){
setTimeout(refreshTable, 1000);
});
}
</script>
</head>
<body background="timebg.jpg">
<div id="tableHolder"></div>
</body>
table.php
<?php
$f_pointer=fopen("csv.txt","r"); // file pointer
while(! feof($f_pointer)){
$csv=fgetcsv($f_pointer);
foreach($csv as &$val){
if($val === "" || $val === false || $val === null) $val = "NA";
}
}
?>
<table>
<tr>
<td><?php echo $csv[2] ?> <?php echo $csv[3]?></td>
</tr>
</table>
Solved
The racer number is $csv1 in my Array from the results file. I found writing the $csv1 to a new CSV file and comparing $csv1 to $lastrace[0] each refresh to work.
Using an if else statement I compared the info and set a variable depending if there was a match or not.If the data matched the variable is '0' and no action is required. If $csv1 did not match $lastrace[0] the variable is '1' and the new race number sent to the lastraceno.txt for future updates.
I could then set a CSS class based on if the variable was 0 or 1.
CSS animation achieved with [https://daneden.github.io/animate.css/]Animate.CSS1
index.php
<head>
<script src="jquery-2.1.3.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
refreshTable();
});
function refreshTable(){
$('#tableHolder').load('table.php', function(){
setTimeout(refreshTable, 1000);
});
}
</script>
</head>
<body background="timebg.jpg">
<div id="tableHolder"></div>
</body>
table.php
<?php
$f_pointer=fopen("csv.txt","r"); // file pointer
while(! feof($f_pointer)){
$csv=fgetcsv($f_pointer);
}
// Replace blank lines with NA
foreach($csv as &$val){
if($val === "" || $val === false || $val === null) $val = "NA";
}
// Get Racer No from previous race
$lastrace = str_getcsv(file_get_contents('lastraceno.txt'));
// Puts current racer no to CSV file
if ($lastrace[0]==="$csv[1]") {
$newrace = 0; // This is not a new race
} else {
$newrace = 1; // This is a new race
$file = fopen("lastraceno.txt","w");
fputcsv($file,explode(',',$csv[1]));
fclose($file);
}
if ($newrace == '1') {
$newtimes = "class='animated zoomIn'";
} else { }
<table <?php echo $newtimes ?>>
<tr>
<td>Text to animate</td>
</tr>
</table.

include loading webpages in slideshow

I am totally new to stackoverflow. I'm trying to adjust an excisting script in which an folder containing photo and video is getting loaded and displayed like a slideshow.
I'd like to add the option to load webpages also. Is there any easy way to do this?
Thank you so much.
This is my code:
<?php
include "class.getFiles.php";
$images = new getFiles();
// list of all files in the images folder (includes videos)
$imageArray = $images->getImageArray();
$sortedImages = new sortFiles();
$sortedImages->sortImageArray($imageArray);
// remove files not in the correct time period
$imageArray = $sortedImages->getImageArray();
$randImage = $sortedImages->randomImageNum();
$fileName = $imageArray[$randImage];
$info = new SplFileInfo($fileName);
?>
<!DOCTYPE html>
<html>
<head>
<title>Fiction Slideshow</title>
<link rel="stylesheet" type="text/css" href="main.css">
</head>
<body>
<?php
if($info->getExtension() == "mp4")
{
echo '<video id="vid" class="videoDisplay" autoplay>
<source src="images/'.$fileName.'" type="video/mp4">
Your browser does not support the video tag.
</video>';
echo '<script type="text/javascript">
var vid = document.getElementById("vid");
vid.addEventListener("ended", function(){
window.location.reload();
});
</script>';
}
else
{
echo '<img class="imageDisplay" src="images/'.$fileName.'" />';
echo '<script type="text/javascript">
setTimeout(function(){
window.location.reload();
}, 30000);
</script>';
}
?>
</body>
</html>
This is the class.getFiles.php file that the other script calls.
<?php
class getFiles{
protected $dir;
protected $imageArray;
function __construct()
{
$this->get_dir();
$this->get_images();
}
protected function get_dir()
{
$this->dir = getcwd();
}
protected function get_images()
{
if(count(scandir($this->dir."/images")) != 2)
{
$this->imageArray = scandir($this->dir."/images");
}
else
{
die("There are no files in the directory");
}
}
public function getImageArray()
{
return $this->imageArray;
}
}
class sortFiles{
protected $sortedImageArray = [];
public function sortImageArray($imageArray)
{
foreach ($imageArray as $imageFile )
{
if($imageFile !== ".." && $imageFile !== ".")
{
$imagePath = $imageFile;
$imageFile = (substr($imageFile, 0, -4));
$BeginningPos = strpos($imageFile, '_');
$beginningDate = (substr($imageFile, 0, $BeginningPos));
$beginningDateformatted = str_replace("-","/", $beginningDate);
$stringToStartTime = strtotime($beginningDateformatted);
$EndingPos = strpos($imageFile, '_', $BeginningPos + strlen('_'));
$EndingPos = $EndingPos + 1;
$EndingDate = (substr($imageFile, $EndingPos));
$EndingDateformatted = str_replace("-","/", $EndingDate);
$stringToEndTime = strtotime($EndingDateformatted);
$time = time();
if($time <= $stringToStartTime && $time >= $stringToEndTime)
{
array_push($this->sortedImageArray, $imagePath);
}
}
}
}
public function getImageArray()
{
if(count($this->sortedImageArray) != 0)
{
return $this->sortedImageArray;
}
else
{
die("There are no files in the time range");
}
}
public function randomImageNum()
{
$imageArrayLength = count($this->sortedImageArray);
$imageRand = rand(0, $imageArrayLength-1);
return $imageRand;
}
}
?>
Well you can save the web pages as links within your media folder. For example if you want to display the web page http://www.example.com, then you can create a file webpage1.txt inside the media folder. This file can have the link http://www.example.com.
In your code you can add a new condition that checks if the file type is txt. If the file type is txt, then your code can read the link inside the file and display the link using an iframe. The following code should work:
else if(strpos($fileName, "weblink") !== false)
{
/** The path to the web page link */
$file_path = (getcwd() . DIRECTORY_SEPARATOR . "images" . DIRECTORY_SEPARATOR . $fileName);
/** Read contents of file */
$web_page_link = file_get_contents($file_path);
/** Display the link in iframe */
echo "<iframe src='".$web_page_link."' width='100%' height='100%'></iframe>";
}
The above code should go above the else statement

Call function php uing jquery

Hello i want to call a function using jquery. I tried a lot of ways and I can't get it.
This my principal webpage.
I'am uploading a file csv and pressing 'Crear' button, it uplaod the file while call the function.
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.3.js"></script>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<SCRIPT type="text/javascript">
$(function (){
$('#btnxml').click(function (){
alert("aki");
$('#contenidos').load('csv.php');
});
});
</SCRIPT>
</head>
<body>
<form action="index.php" id="filecsv" method="post" enctype="multipart/form-data">
<input type="file" multiple="multiple" id="file" name="up_csv[]"/>
<input type="submit" value="Cargar" name="btnxml" id="btnxml" /><br />
</form>
<?php
global $archivocsv;
//tipos de archivos permitidos
$extensionxml = array('csv','txt');
//destino
$rutaupcsv = './csv/';
//multicargador de archivos
$vt=0;
for($i=0;$i<count($_FILES['up_csv']['size']);$i++){
for ($j=-1; $j<count($extensionxml); $j++) {
if (strripos($_FILES['up_csv']['name'][$i], $extensionxml[$j])!== false) {
$filename = 'lista';
$destino = $rutaupcsv.$_FILES['up_csv']['name'][$i];
$archivocsv = basename($_FILES['up_csv']['name'][$i]);
move_uploaded_file($_FILES['up_csv']['tmp_name'][$i],$destino);
$vt=$vt+1;
break;
}
$ns=1;
}
}
?>
<div id="contenidos"></div>
csv.php
<?php
echo '<html>';
echo '<head>';
echo '<meta content="text/html;charset=utf-8" http-equiv="Content-Type">';
echo '<meta content="utf-8" http-equiv="encoding">';
echo '</head>';
function makecsv() {
global $archivocsv;
$csv = './csv/' . $archivocsv;
$doc = new DOMDocument();
$row = 1;
$handle = fopen($csv, "r");
# Rows Counter
$csvxrow = file($csv);
$csvxrow[0] = chop($csvxrow[0]);
$anzdata = count($csvxrow);
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
$row++;
#Load Predefined XML Template
$xml2 = $xml;
$xmlruta = './Templates/';
$xml = $xmlruta.$data[1].'.xml';
$doc->load($xml);
$xp = new DOMXPath($doc);
for ($c=0; $c < $num; $c++) {
foreach($xp->query('/ROOT/HEADER/#KEY[. != ""]') as $attrib)
{
$attrib->nodeValue = $data[0];
}
foreach($xp->query('/ROOT/DATA/SAPMES/LOIPRO/E1FKOL/#AUFNR[. != ""]') as $attrib)
{
$attrib->nodeValue = $data[0];
}
foreach($xp->query('/ROOT/DATA/SAPMES/LOIPRO/E1FKOL/#MATNR[. != ""]') as $attrib)
{
$attrib->nodeValue = $data[1];
}
foreach($xp->query('/ROOT/DATA/SAPMES/LOIPRO/E1FKOL/#GAMNG[. != ""]') as $attrib)
{
$attrib->nodeValue = $data[2];
}
foreach($xp->query('/ROOT/DATA/SAPMES/LOIPRO/E1AFFLL/E1FVOL/#MGVRG[. != ""]') as $attrib)
{
$attrib->nodeValue = $data[2];
}
foreach($xp->query('/ROOT/DATA/SAPMES/LOIPRO/E1FKOL/#GSTRS[. != ""]') as $attrib)
{
$attrib->nodeValue = $data[3];
}
foreach($xp->query('/ROOT/DATA/SAPMES/LOIPRO/E1FKOL/#GLTRS[. != ""]') as $attrib)
{
$fecha = new DateTime($data[3]);
$fecha->add(new DateInterval('P1M'));
$attrib->nodeValue = $fecha->format('Y-m-d');
}
}
$name = $data[0] .'-'. $data[1];
$doc->formatOutput = true;
echo $doc->saveXML();
$rutafinal = './XML/';
$doc->save($rutafinal.$name.'.xml');
}
fclose($handle);
echo $anzdata . " XML Creados" . "<br />";
return $data;
}
makecsv();
echo '</html>';
?>
I can't call the function.
it doesn't do anything when i try to call it.
EDIT: I think the problem is in my function. function edite
Javascript canĀ“t play with php directly because JS is client side (only in browser) and PHP is server side (only in browser). What you can do is a PHP file that has the code you want to invoke, and make JS call that page.
Separate the CVS code from the form and make JS call the new php with the CVS php functionality.
jQuery runs in the client's browser whereas your PHP is running on your web server. If you wish to call a PHP function from your jQuery code, your best option is to do so using AJAX.
You can find documentation for implementing an AJAX call in jQuery here: https://api.jquery.com/jQuery.ajax/
You'll need to print the actual hmtl to do the function.
PHP
<?php
print '<script> makecsv() </script>';
?>

Randomize photos from a directory via PHP

I have the following code that is functional that will randomize the photos I have in my 'photos' folder each time the refresh button is clicked. I know this may not be the most efficient way for this to be coded but for my matter it works. I am looking for help regarding my PHP code that will make the photos more random. I currently have 200+ pictures in the folder and often get repeated pictures more than I'd like. What changes to it can I make? (PS. ignore the AJAX/JavaScript I was playing around with)
<html>
<head>
<title>Pictures!</title>
<style type="text/css">
body{ background-color:D3DFDE; }
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
</head>
<body>
<div id='main'>
<?php
function randomimages(){
$dirname = isset($_REQUEST['dir'])? $_REQUEST['dir'] : './photos/';
$numimages = isset($_REQUEST['num'])? $_REQUEST['num'] : 1;
$pattern = '#\.(jpg|jpeg|png|gif|bmp)$#i';
$files = array();
if($handle = opendir($dirname)){
while(($file = readdir($handle)) !== false){
if(preg_match($pattern, $file)){
array_push($files, "<center><img src='" . $dirname . $file . "' alt='' /></br><br/><hr/></center>");
}
}
closedir($handle);
shuffle($files);
}
return implode("<center><br/>", array_slice($files, 0, $numimages)) . "<br/> </center>";
}
?>
<!-- <center><a id="myButton" href="#">MAS PICTURES!</a></center> -->
<center><input type='button' onClick='window.location.reload(true)' value='MAS PICTURES!!!' style="height:200px; width:150px" /></center>
<hr/>
<script type="text/javascript">
$(function() {
$("#myButton").click(function() {
$("#main").load("index.php");
});
});
</script>
<?php echo randomimages(); ?>
<center>Created by: Matt & Joe</center>
</div>
</body>
</html>
You can do the following:
Optimize the code by not reading the directory over and over. What you can do this by reading the directory once (and say then store the entries as an array in APC cache). Set a timeout for this APC key to bust the cache once in a while.
Call the `mt_rand` function with min as `0` and max as `count(array)-1` and access that index.
Generic code to read from directory can be as follows (needs modification to match your needs):
<?php
function &list_directory($dirpath) {
if (!is_dir($dirpath) || !is_readable($dirpath)) {
error_log(__FUNCTION__ . ": Argument should be a path to valid, readable directory (" . var_export($dirpath, true) . " provided)");
return null;
}
$paths = array();
$dir = realpath($dirpath);
$dh = opendir($dir);
while (false !== ($f = readdir($dh))) {
if (strpos("$f", '.') !== 0) { // Ignore ones starting with '.'
$paths[] = "$dir/$f";
}
}
closedir($dh);
return $paths;
}
Provide the directory full path to the variable $dirpath
$image_source_array=scandir($dirpath);
sort($image_source_array);
Use mt_rand function with min as 0 and max as count($image_source_array)-1 and access that index from the array to get the image name
and then access the image with the $dirpath/image name you will get the random image each time
Create function like this it will be the shortest approch
function randomimages() {
$dirname = isset($_REQUEST['dir']) ? $_REQUEST['dir'] : './photos/';
$image_source_array = scandir($dirname);
sort($image_source_array);
$image_count = count($image_source_array) - 1;
$rand_index = mt_rand(3, $image_count);
//Starting with 3 because scandir returns directory also in the 2 indexes like '.' and '..'
$rand_image_path = $dirname . $image_source_array[$rand_index];
return $rand_image_path;
}
For the sake of simplicity and reusability, you might want to use RegexIterator together with DirectoryIterator:
function randomimages($path, $num_images)
{
$images = array();
foreach (new RegexIterator(new DirectoryIterator($path),
'#\.(jpe?g|gif|png|bmp)$#i') as $file) {
$images[] = $file->getPathname();
}
shuffle($images);
return array_slice($images, 0, $num_images);
}
Using:
$path = isset($_REQUEST['dir']) ? $_REQUEST['dir'] : './photos/';
$num_images = isset($_REQUEST['num']) ? $_REQUEST['num'] : 1;
print implode('<br />', randomimages($path, $num_images));

Categories