Forum Moderators: coopster
I`ve written an upload script that lets people upload files to my server. The info gets stored in a text file, in the format:
date ¦ name ¦ email ¦ file ¦ size
This works fine. I`ve then done an admin page to show the info in a browser, which again works fine. I`ve popped a delete link next to each file in case I want to delete any. This uses the unlink() function and again works fine, whatever has been uploaded gets removed when the corresponding delete button is clicked. No probs so far.
The problem I have is that the info remains in the text file. I haven`t really worked with text files much before, so I was wondering how I remove the corresponding line from the text file as well as deleting the file? So it then disappears completely from the admin listing?
Thanks for the help!
:)
$fp = fopen($filename,"r+");
$counter = 0;
while($linetemp = fgetcsv($fp,10000,"¦")) {
if ($counter!= $rownum) {
$linearr[$counter] = $linetemp;
}
$counter++;
unset($linetemp);
}
fclose($fp);
$fp = fopen($filename,"w+");
$writestr = "";
foreach ($linearr as $whoknows) {
$writestr .= implode("¦",$whoknows) . "\n";
}
fwrite($fp,$writestr);
fclose($fp);
It gives the records a $rownum on output and then when you delete a line it passes that $rownum to this piece above and when the numbers match it just skips that record and then writes the file again with out it.
always replace broken pipes with "real" pipes
I`ve come up with the following which seems to work:
if ($action == "delete")
{
$contents = file($server_path . "log/uploads.log");
$before = $row-1;
$after = $row+1;for($i = 0; $i < $before; $i++)
{
$remainder .= $contents[$i];
}
for($j = 0; $j > $after; $j++)
{
$remainder .= $contents[$j];
}
$fp = fopen($server_path . "log/temp.log", "ab");
if ($fp!= false)
{
fwrite($fp, $remainder);
fclose($fp);}
@unlink($server_path . "log/uploads.log");
@rename($server_path . "log/temp.log", $server_path . "log/uploads.log");
@unlink($server_path . "uploads/" . $file);fileDeleted();
}
The variable $row holds the row number and is passed in the url. I work out whats before that line and whats after it a la vincevincevince`s suggestion, then write to a new directory, delete the old and rename the new.
It seems to work fine, so I`m happy with that. If you think that I should include anything else, please let me know.
Thanks!
Since you know the row number and don't have to test each array element with a regex or something, here's a thoroughly untested idea that might work and saves a lot of looping. Note that I'm assuming that $row = the array index of that row, so row 1 is $row==0. Like I say, untested, including a high probability of unmatched parentheses, so you might get a parse error, but the idea should work. If you bite and give it a try, I'd love to hear back about how it went.
if ($action == "delete")
{
$contents = implode("\n", array_splice(file($path . "log/uploads.log"), $row, 1)); // comment 1
if ($fp = fopen($server_path . "log/temp.log", "ab")) // comment 2
{
fwrite($fp, $contents);
fclose($fp);
}
@unlink($server_path . "log/uploads.log");
@rename($server_path . "log/temp.log", $server_path . "log/uploads.log");
@unlink($server_path . "uploads/" . $file);
fileDeleted();
}
}
Comment 1
This is the equivalent of
$contents = file($server_path . "log/uploads.log"); //comment 1
$contents = array_splice($contents, $row, 1);
$contents = implode("\n", $contents);
Comment 2
All of these are functionally the same, the last is the most economical:
1.
$fp = fopen($server_path . "log/temp.log", "ab");
if ($fp!= false)
2.
$fp = fopen($server_path . "log/temp.log", "ab");
if ($fp == true)
3.
$fp = fopen($server_path . "log/temp.log", "ab");
if ($fp)
4.
if ($fp = fopen($server_path . "log/temp.log", "ab"));
Comment 3.
for($j = 0; $j > $after; $j++)
{
$remainder .= $contents[$j];
}
Yous say this works so I believe you. Maybe I'm just dense, but I can't figure out how. As I read it, it would fail the test on the first time through unless $after < 0 (i.e. $row is 0 in your example), in which case it runs as an infinite loop (or in this case stops when it addresses an array index out of range and everything crashes). Are you sure you aren't truncating your file at $row?
If you don't like my non-loop solution (or it doesn't work - I haven't tried it), I would do something like this
for ($j=$row; $j<count($contents); $j++)
{
$remainder .= $contents[$j];
}
Tom
I`ve added your code and it works great, just one thing. When I delete the last entry, I get the following message:
Warning: Invalid argument supplied for foreach() in /blah/blah/blah/admin.php on line 69
Any ideas?
If I can just figure out the error with the foreach loop, jatar_k`s example works just fine.
Thanks for the coding help.
:)