Variable for marking documents created each day, resetting every 24 hours - php

I'm using TCPDF along with FPDI to create documents in PDF based on a template using a PHP form.
I need a way to ID them. The problem is - most of these documents were already created manually, thus having ID format already specified.
It's basically Name-DD.MM.YYYY-X.pdf and it can't change.
For example, Document-01.01.2014-2, where 2 means it's a second document issued that day.
Is there a way to do that automatically? I'm using a traditional <form> with action set to the PHP TCPDF script and it works flawlessly, but how to specify that if something was already generated today then do $var = $var + 1 and then reset it at midnight?

You could try using the function file_exists(), in order to test if the base name is already generated or not.
If it is, simply create a loop and increment your $var to test iteratively your documents.
Example:
$baseName = "Name-DD.MM.YYYY";
$extension = ".pdf";
$i = 0;
while(1)
{
if($i > 0)
$testName = $baseName."-".$i.$extension;
else
$testName = $baseName.$extension;
if(!file_exists($testName))
break;
$i++;
}
if($i > 0)
$validName = $baseName."-".$i.$extension;
else
$validName = $baseName.$extension;
Hoping my answer would help you,
Venom

Related

PHP - Trying to show Next and Previous file from the same directory

As the title sais, I'm trying to get the next and previous file from the same directory. So I did some this like this. Is there any better way of doing it? (This is from next auto index file.php code about related files, I have change it for my needs.)
db screenshot if you want to look - ibb.co/wzkDxd3
$title = $file->name; //get the current file name
$in_dir=$file->indir; //current dir id
$r_file = $db->select("SELECT * FROM `". MAI_PREFIX ."files` WHERE `indir`='$in_dir'"); //all of the file from the current dir
$rcount=count($r_file);
$related='';
if($rcount > 2){
$i = 0; // temp variable
foreach($r_file as $key => $r){ //foreach the array to get the key
if($r->name == $title){ //Trying to get the current file key number
$next =$key+1; //Getting next and prev file key number
$prv =$key-1;
foreach($r_file as $keyy => $e){ //getting the file list again to get the prev file
if($prv == $keyy){
$related .=$e->name;
}
}
foreach($r_file as $keyy => $e){ // same for the next file
if($next == $keyy){
$related .=$e->name;
}
}
}
}
Without knowing your DB background and use case, there still should be the possibility to use something like $r_file[$key], $r_file[$next] and $r_file[$prev] to directly access the specific elements. So at least two of your foreach loops could be avoided.
Please note, that nesting loops is extremely inefficient. E. g., if your $r_file contains 100 elements, this would mean 10.000 iterations (100 times 100) with your original code!
Also, you should leave a loop as soon as possible once its task is done. You can use break to do this.
Example, based on the relevant part of your code and how I understand it is supposed to work:
foreach($r_file as $key => $r){ //foreach the array to get the key
if($r->name == $title) { //Trying to get the current file key number
$next =$key+1; //Getting next and prev file key number
$prv =$key-1;
$related .= $r_file[$prv]->name; //Directly accessing the previous file
$related .= $r_file[$next]->name; //Directly accessing the next file
break; // Don't go on with the rest of the elements, if we're already done
}
}
Possibly, looping through all the elements to compare $r->name == $title could also be avoided by using some numbering mechanisms, but without knowing your system better, I can't tell anything more about that.

Need Help on the below modification [duplicate]

I am fairly new to the php world and have been creating an inventory tracking system for one of my side businesses. Most of the basics are working, but I am having issues with my "upload pdf" function. Even though it works and uploads the pdf file to its target location, I cannot get the file name ($docid) to be an integer that auto increments every time there is a submission so that files never have the same name. Below is the code I have working:
$pdfPath = "/Documents/TEST/";
$maxSize = 102400000000;
$docid = TEST;
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['upload_pdf'])) {
if (is_uploaded_file($_FILES['filepdf']['tmp_name'])) {
if ($_FILES['filepdf']['type'] != "application/pdf") {
echo '<p>The file is not in PDF</p>';
} else if ($_FILES['filepdf']['size'] > $maxSize) {
echo '<p class="error">File is too big! Max size is =' . $maxSize . 'KB</p>';
} else {
$menuName = "Order_Receipt_".$docid.".pdf";
$result = move_uploaded_file($_FILES['filepdf']['tmp_name'], $pdfPath . $menuName);
if ($result == 1) {
echo '<META HTTP-EQUIV=Refresh CONTENT="0; URL=http://localhost/website/enter_new_order_success.html">';
} else {
echo '<p class="error">Error</p>';
}
}
}
I know I need some sort of loop to auto increment that $docid variable but I cannot seem to figure it out. I have read up on the topic, but auto increment with the if statement is throwing me off. Any help would be greatly appreciated.
Cheers
Well, unless you store the entries to keep track in a database or similar you could check what entries you have in your upload folder and increment it by one.
The glob function is useful for that:
http://php.net/manual/en/function.glob.php
$myFiles = sort(glob('/Documents/TEST/*.pdf')); // returns an array of pdf files in the target folder. Using sort to sort the array e.g. file_1_.pdf,file_2_.pdf,file_3_.pdf, etc
//last element
$lastFile = end($myFiles); //returns the last file in the array
//get the number and increment it by one
$number = explode('_',$lastFile);
$newNumber = $number[1] + 1; //add this to the name of your uploaded php file.
$pdfUploadedFile= "Order_Receipt_".$newNumber."_.pdf";
As pointed out in the comments... I find it a better idea to name it with a timestamp generated string. And also don't forget the quotes around your strings.
$docid = TEST;
should be:
$docid = 'TEST';
Edit
Even better would be naming it in a formatted date I suppose.
$pdfUploadedFile= "Order_Receipt_".date("Y-m-d-H-i-s").".pdf"; // will output something like Order_receipt_2014-09-24-11-14-44.pdf

PHP incrementing all IDs in a CSV

thanks for reading!
I have an app that allows people to add, edit and delete items in a CSV. I've encountered a bug where if there are non-unique IDs and you try to edit or delete them, it will edit or delete all of them, as the system parses through the spreadsheet to find the ID - which also corresponds to the object's order when using it so the user must be able to change the ID
The solution I've come up with is quite simple, should the user edit an object and change its ID to one that already exists, then the system will take all of the objects with an ID bigger than or equal to the new ID and increment them all by one.
The following code is my if statement that checks whether the ID already exists
if($exists == "true") //does the $newImageID already exist in the gallery?
{
$table = fopen($fullURL,'r'); //$fullURL is the location of the CSV tested and works
$temp_table_two = fopen($tempURL,'w');
while (!feof($temp_table_two) ) {
$getid = fgetcsv($temp_table_two, 1024);
if($getid[0] >= $newImageID)
{
// $getid[0]++; //increase id in temp_table_two by 1 if it is > $newImageID
echo $getid[0];
}
}
fclose($table);
fclose($temp_table);
rename($tempURL,$fullURL);
}
This code takes place after fopen and before fclose. In context, $exists is either "true" or "false" (will change to boolean later on), the while loop parses through my $temp_table (a fopen) and if the first column object (the ID) is equal to or bigger than the one in the new ID then it is incremented. This means that the new object gets "slotted in" so to speak and pushes the rest down
Strangely my request is timing out after a long spinner after I execute this code and I have no idea what the problem is
Thanks for all your help in advance
EDIT: I have found the source of the problem is the while loop itself, should I comment everything out as such:
while (!feof($temp_table_two) ) {
$getid = fgetcsv($temp_table_two, 1024);
// if($getid[0] >= $newImageID)
// {
// // $getid[0]++; //increase id in temp_table_two by 1 if it is > $newImageID
// echo $getid[0];
// }
}
The code still doesn't work yet the only thing left to run is the loop that doesn't do anything
EDIT 2:
Following an answer, I did away with the temp table and just work from the table itself, this if statement is executed BEFORE adding the new data with its ID
if($exists == "true") //does the $newImageID already exist in the gallery?
{
$table = fopen($fullURL,'r+');
while (!feof($table) ) {
$getid = fgetcsv($table, 1024);
if($getid[0] >= $newImageID)
{
echo $getid[0];
$getid[0]++; //increase id in temp_table_two by 1 if it is > $newImageID
}
}
fclose($table);
}
The code no longer times out, but the items inside $getid[0] are not incremented. I have echoed them and it does echo all of the ID's equal to or bigger than my $newImageID but the $getid[0]++; doesn't seem to be affecting the CSV at all
You are testing if you reach the end of the temp file and that's wrong. You need to check the origin file and also read from it!
while (!feof($table) ) {
$getid = fgetcsv($table, 1024);
Try this:
if ($csv = fopen($temp_table_two, 'r+')) do {
$getid = fgetcsv($csv, 1024);
if($getid[0] >= $newImageID)
{
echo $getid[0]; // $getid[0]++;
}
} while (!feof($csv));
That will prevent your while loop from timing out due to being stuck in an infinite if there is a problem opening the file. feof will return true only if it reaches EOF, it will return false otherwise which will cause it to never be able to break out.
For actually writing your data back to the CSV file, your current code won't work as fgetcsv just gives you an array representation of a CSV line in the file. Writing to that array just changes the array, not back to the file.
For that, see this similar answer: Append data to middle line/row of a csv instead of the last line or row
or
http://php.net/manual/en/function.fputcsv.php

Auto increment file names PHP/MySQL

I am fairly new to the php world and have been creating an inventory tracking system for one of my side businesses. Most of the basics are working, but I am having issues with my "upload pdf" function. Even though it works and uploads the pdf file to its target location, I cannot get the file name ($docid) to be an integer that auto increments every time there is a submission so that files never have the same name. Below is the code I have working:
$pdfPath = "/Documents/TEST/";
$maxSize = 102400000000;
$docid = TEST;
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['upload_pdf'])) {
if (is_uploaded_file($_FILES['filepdf']['tmp_name'])) {
if ($_FILES['filepdf']['type'] != "application/pdf") {
echo '<p>The file is not in PDF</p>';
} else if ($_FILES['filepdf']['size'] > $maxSize) {
echo '<p class="error">File is too big! Max size is =' . $maxSize . 'KB</p>';
} else {
$menuName = "Order_Receipt_".$docid.".pdf";
$result = move_uploaded_file($_FILES['filepdf']['tmp_name'], $pdfPath . $menuName);
if ($result == 1) {
echo '<META HTTP-EQUIV=Refresh CONTENT="0; URL=http://localhost/website/enter_new_order_success.html">';
} else {
echo '<p class="error">Error</p>';
}
}
}
I know I need some sort of loop to auto increment that $docid variable but I cannot seem to figure it out. I have read up on the topic, but auto increment with the if statement is throwing me off. Any help would be greatly appreciated.
Cheers
Well, unless you store the entries to keep track in a database or similar you could check what entries you have in your upload folder and increment it by one.
The glob function is useful for that:
http://php.net/manual/en/function.glob.php
$myFiles = sort(glob('/Documents/TEST/*.pdf')); // returns an array of pdf files in the target folder. Using sort to sort the array e.g. file_1_.pdf,file_2_.pdf,file_3_.pdf, etc
//last element
$lastFile = end($myFiles); //returns the last file in the array
//get the number and increment it by one
$number = explode('_',$lastFile);
$newNumber = $number[1] + 1; //add this to the name of your uploaded php file.
$pdfUploadedFile= "Order_Receipt_".$newNumber."_.pdf";
As pointed out in the comments... I find it a better idea to name it with a timestamp generated string. And also don't forget the quotes around your strings.
$docid = TEST;
should be:
$docid = 'TEST';
Edit
Even better would be naming it in a formatted date I suppose.
$pdfUploadedFile= "Order_Receipt_".date("Y-m-d-H-i-s").".pdf"; // will output something like Order_receipt_2014-09-24-11-14-44.pdf

Crunch lots of files to generate stats file

I have a bunch of files I need to crunch and I'm worrying about scalability and speed.
The filename and filedata(only the first line) is stored into an array in RAM to create some statical files later in the script.
The files must remain files and can't be put into a databases.
The filename are formatted in the following fashion :
Y-M-D-title.ext (where Y is Year, M for Month and D for Day)
I'm actually using glob to list all the files and create my array :
Here is a sample of the code creating the array "for year" or "month" (It's used in a function with only one parameter -> $period)
[...]
function create_data_info($period=NULL){
$data = array();
$files = glob(ROOT_DIR.'/'.'*.ext');
$size = sizeOf($files);
$existing_title = array(); //Used so we can handle having the same titles two times at different date.
if (isSet($period)){
if ( "year" === $period ){
for ($i = 0; $i < $size; $i++) {
$info = extract_info($files[$i], $existing_file);
//Create the data array with all the data ordered by year/month/day
$data[(int)$info[5]][] = $info;
unset($info);
}
}elseif ( "month" === $period ){
for ($i = 0; $i < $size; $i++) {
$info = extract_info($files[$i], $existing_file);
$key = $info[5].$info[6];
//Create the data array with all the data ordered by year/month/day
$data[(int)$key][] = $info;
unset($info);
}
}
}
[...]
}
function extract_info($file, &$existing){
$full_path_file = $file;
$file = basename($file);
$info_file = explode("-", $file, 4);
$filetitle = explode(".", $info_file[3]);
$info[0] = $filetitle[0];
if (!isSet($existing[$info[0]]))
$existing[$info[0]] = -1;
$existing[$info[0]] += 1;
if ($existing[$info[0]] > 0)
//We have already found a post with this title
//the creation of the cache is based on info[4] data for the filename
//so we need to tune it
$info[0] = $info[0]."-".$existing[$info[0]];
$info[1] = $info_file[3];
$info[2] = $full_path_file;
$post_content = file(ROOT_DIR.'/'.$file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$info[3] = $post_content[0]; //first line of the files
unset($post_content);
$info[4] = filemtime(ROOT_DIR.'/'.$file);
$info[5] = $info_file[0]; //year
$info[6] = $info_file[1]; //month
$info[7] = $info_file[2]; //day
return $info;
}
So in my script I only call create_data_info(PERIOD) (PERIOD being "year", "month", etc..)
It returns an array filled with the info I need, and then I can loop throught it to create my statistics files.
This process is done everytime the PHP script is launched.
My question is : is this code optimal (certainly not) and what can I do to squeeze some juice from my code ?
I don't know how I can cache this (even if it's possible), as there is a lot of I/O involved.
I can change the tree structure if it could change things compared to a flat structure, but from what I found out with my tests it seems flat is the best.
I already thought about creating a little "booster" in C doing only the crunching, but I since it's I/O bound, I don't think it would make a huge difference and the application would be a lot less compatible for shared hosting users.
Thank you very much for your input, I hope I was clear enough here. Let me know if you need clarification (and forget my english mistakes).
To begin with you should use DirectoryIterator instead of glob function. When it comes to scandir vs opendir vs glob, glob is as slow as it gets.
Also, when you are dealing with a large amount of files you should try to do all your processing inside one loop, php function calls are rather slow.
I see you are using unset($info); yet in every loop you make, $info gets new value. Php does its own garbage collection, if thats your concern. Unset is a language construct not a function and should be pretty fast, but when using not needed, it still makes whole thing a bit slower.
You are passing $existing as a reference. Is there practical outcome for this? In my experience references make things slower.
And at last your script seems to deal with a lot of string processing. You might want to consider somekind of "serialize data and base64 encode/decode" solution, but you should benchmark that specifically, might be faster, might be slower depenging on your whole code. (My idea is that, serialize/unserialize MIGHT run faster as these are native php functions and custom functions with string processing are slower).
My answer was not very I/O related but I hope it was helpful.

Categories