I have a CSV file with three columns:
Mary,150203_15:29:12,150203_16:10:12
John,150203_15:29:17,pending
Peter,150203_15:29:35,150203_15:49:35
Olga,150203_15:30:43,pending
...
..
.
Mary,150204_15:42:14,pending
Peter,150204_20:42:14,pending
Because there are many entries on that file all I want to do is
find the latest entry according to the Username and change the last value (from pending to date()).
In the example above lets say I want to change the latest Mary entry in the 3rd column from pending to date. Then replace the updated CSV file with the current one.
Any ideas on how to approach that?
Thank you
You can work with the file as one huge string and do a string replacement.
$data = file_get_contents('your_file.csv');
$data = str_replace('Joe,150203_16:21:43,pending','Joe,15203_16:21:43,15204_15:23:43',$data);
file_put_contents('your_file.csv', $data);
The comments below raise a concern of finding out what the latest date is for a name. That is also rather simple to do. Assuming you've loaded $data in, as above...
$matches = array(); // Just to point out that this is an array
preg_match_all("/Joe,(.*),/", $data, $matches);
Now, $matches[1] contains all the dates for Joe. Did you ONLY want the ones that are pending? No problem...
preg_match_all("/Joe,(.*),pending/", $data, $matches);
Now, $matches[1] only contains the pending dates. Which is the most recent?
rsort($mathes[1]);
Now, $matches[1][0] is the most recent date. So, you can do:
$data = str_replace('Joe,'.$matches[1][0].',pending','Joe,'.$matches[1][0].',15204_15:23:43',$data);
Is this the absolute most efficient way to do this? No. Is it impossibly hard? No. You should look into using a proper database, but it is possible to use csv files.
If moving the data to a DB is not a solution in your case, you could do the following:
Read the CSV file into PHP via fgetcsv(), line by line, into an
array
Sort the array based on your criteria and get the latest entry
Update the entry
Write the entries back into the file via fputcsv()
I actually found a much simpler solution to this. Was the simplest one I could come up with.
$line = $_SESSION[username].",".$_SESSION[LOGIN_TIME].",".'pending'."\r\n";
$newline = $_SESSION[username].","$_SESSION[LOGIN_TIME].",".date("ymd_H:i:s"). "\r\n";
$data = file_get_contents('login.log');
$data = str_replace($line,$newline,$data);
file_put_contents('login.log', $data);
So there is no need for scanning for the latest entry. I just store the previous entry values and replace them with the new ones.
Thank you kainaw and BigScar
Related
I apologize if this question has a no brainer answer. I am still learning more ins and outs of php.
I have a snippet of code that is taking in a CSV file. This CSV file is uploaded by a user who downloads it from an external source. In the CSV file, the person's first name and last name is not split in separate columns. Therefore, in PHP the following is used:
$member_name = explode( " ", $application_data[5]);
The problem is that when this data is then used to render a PDF document to send a letter to the member, it cuts off their last name if their last name is two words.
The information is loaded into the PDF document with the first name and last name field by using:
$member_name[0],
$member_name[1]
Can I safely do:
$member_name[0],
$member_name[1] + $member_name[2]
Even if 99% of the members do not have a space in the last name? Will I get an error that member_name[2] doesn't exist 99% of the time this is done?
I've done some searching on array_merge. Is that a better option? I've been trying to search for how php handles when you add something that doesn't exist and I'm drawing a blank.
I don't want to assume my solution will work and then when the person uploads their CSV file tomorrow, they get an error.
Or maybe I'm looking at this the wrong way and before it attempts to render a pdf document, I should do an if statement that figures out if $member_name[2] exists.
Thank you!
You can use the limit parameter of explode to only split at the first space.
$member_name = explode( " ", $application_data[5], 2);
Of course, if the first name also has more than one word, this still won't be quite right. Names are tricky.
Regarding array_merge, I don't think it would really be useful in this situation.
You could just use a limiter on your explode to only seperate on the first space. Here is an example.
$name = "George The King";
print_r(explode(' ', $name, 2)); //prints -> Array ( [0] => George [1] => The King )
I have a csv file which contains 2000 data in one single column. The data format is like following:
name 100/1
name 100/2
name 105/6
...
So the general format is 'text integer_one/integer_two' Now I want it to store in a mysql database table with 2 columns. column_1 should have the data integer_one, and column_2 should have the data integer_two
How can I do this using php to push the data into mysql?
First start by extracting your values. If all your data is formated like in your example, you can use a simple explode.
$lines = explode(",", $data); // $data should be your file extracted into a string
foreach ($lines as $line) {
$temp = explode(" ", $line);
$name = $temp[0];
$temp_2 = explode("/", $temp[1]);
$integer_1 = $temp_2[0];
$integer_2 = $temp_2[1];
$query = "INSERT INTO table_two_columns SET name = '{$name}', integer_1 = '{$integer_1}', integer_2 = '{$integer_2}'";
}
Well that's my take on your problem.
Use ph function fgetcsv function to read a csv file (example is give in this page) then take each in loop and parse it using function explode() and create query from it and save in database
Take a look at preg_match, you should be able to get these values using a fairly trivial regular expression, like:
preg_match(/\w+\s*(\d+)\\\/(\d+)/, $row, $matches);
var_dump($matches);
To pull the data from a file take a look at fgets there are example of reading the file line-by-line to get the $row variable in the code above.
You can then write each line to the database using an INSERT statement.
Some things to consider:
How large is the file?
How often do you need to insert this data - is it a one-off?
These things will influence how you build your code; there are multiple ways to bulk insert data, and if this is just a one-off run then I would suggest maniuplating the text data using sed or similar, and then bulk inserting using the native methods of your database of choice (for mysql see LOAD DATA INFILE, or using the \. option in the client)
If the file is large and you need to insert things regularly, look at using prepared statements, and/or the multiple insert syntax:
INSERT INTO mytable (name, number, anothernumber) VALUES('paul', 1, 2),('bob',2,1)
have a look at fopen() and fread() or fgetcsv() php functions to handle the files, with them you should be able to loop through the lines of the cvs file, If you have control over your server configuration, I would suggest you to have a look into SplFileObject instead, because you can handle the files more efficient/elegantly, and object oriented. but require you to enable SPL. This last one is my recommendation, as you could read the file like this:
function random_name(){
$file_name = "names.csv";
if(is_readable($file_name)){
$file = new SplFileObject($file_name);
$file->seek($file->getSize());
$linesTotal = $file->key();
$file->seek(rand(1,$linesTotal-1));
$line = $file->fgetcsv();
return $line[4];
}
}
This was a sample script of mine to get a random name from a 1000 name cvs file.
As you loop and get the file information, you can then use explode(), this function separates your string by the separator you define, in your case it would be:
$array = explode("/", $myLine);
And you would access like this:
$array[0] or $array[1] to get the value
I am having a few issues in doing something that I am sure is quite simple.
I have had a look for many hours on Google and stackoverflow but I can't seem to find an answer. What I did find that was similar I tried to modify, but unfortunately without success.
I have a text file (names.txt) that contains values similar to this:
Jim|Bob|Keith|Fred|Steve<br>
I need a script that I can run every minute to change the content of the file to store the values in the same format but alphabetically:
Bob|Fred|Jim|Keith|Steve<br>
then display them in an html dropdown box as options.
Any assistance would be very much appreciated. Thanks in advance for your assistance.
You could try this:
$fileName = 'names.txt';
$data = file_get_contents($fileName);
// Assuming that the file had the data in one line...
// Split the data using the delimiter
$split = explode("|", $data);
// Sort
sort($split);
// Put it all back together
$data = implode("|", $split);
// Store it back in the file
file_put_contents($fileName, $data);
I'm trying to make a form where the user can add their own 'questions + answers' to the quiz.
I loaded the original questions from a text file. The added questions will then be processed by process_editadd.php
<?php
session_start();
$file = fopen('data.txt', 'r');
$array=$_SESSION['questions_array'];
//make array out of values
$q=array($_POST['question'],$_POST['one'],$_POST['two'],$_POST['three'],$_POST['four']);
//add to file
$file=fopen("data.txt","w+");
fwrite($file, implode(',', $q)).
header('Location:module.php');
?>
The array adds onto the text file, but the problem is that it replaces the whole thing. I don't want the questions to replace the previous ones, I just want them added. Do you guys know what's wrong with the code?
Note: I'm not allowed using mySQL or Javascript
You could switch to using an actual database and make your life a lot easier... Failing that, look into fputcsv and fgetcsv to make it a slightly less tedious problem.
Your implode version right now is also vulnerable to CSV injection... you don't handle the case where any of the text you're writing MIGHT contain a comma. If it does, you'll suddenly find you'll have extra "columns" when you read the data back in later on.
I am trying to create a database field merge into a document (rtf) using php
i.e if I have a document that starts
Dear Sir,
Customer Name: [customer_name], Date of order: [order_date]
After retrieving the appropriate database record I can use a simple search and replace to insert the database field into the right place.
So far so good.
I would however like to have a little more control over the data before it is replaced. For example I may wish to Title Case it, or convert a delimited string into a list with carriage returns.
I would therefore like to be able to add extra formatting commands to the field to be replaced. e.g.
Dear Sir,
Customer Name: [customer_name, TC], Date of order: [order_date, Y/M/D]
There may be more than one formatting command per field.
Is there a way that I can now search for these strings? The format of the strings is not set in stone, so if I have to change the format then I can.
Any suggestions appreciated.
You could use a templating system like Smarty, that might make your life easier, as you can do {$customer_name|ucwords} or actually put PHP code in your email template.
Try a RegEx and preg_replace_callback:
function replace_param($matches)
{
$parts = explode(',',$matches[0]);
//$parts now contains an array like: customer_name,TC,SE,YMD
// do some substitutions and:
return $text;
}
preg_replace_callback('/\[([^\]]+)\]/','replace_param',$rtf);
You can use explode on it to separate them into array values.
For Example:
$customer_name = 'customer_name, TC';
$get_fields = explode(',', $customer_name);
foreach($get_fields as $value)
{
$new_val = trim($value);
// Now do whatever you want to these in here.
}
Sorry if I'm not understanding you.