I'm working on a file based commenting system with in-line comments (only 1 level).
Despite being a newby I've managed to create a system in which users are able to add new comments and use #[NUMBER] to add their reply below another comment.
My file and folder structure looks like this:
/threads/
1/
1.txt
2.txt
3.txt
2/
1.txt
3/
1.txt
2.txt
3.txt
4.txt
The folder in threads has the thread number (used to make a reply) for its name and 1.txt contains the contents of the "mother" post. Every post higher than 1 is a reply.
So I could show the threads in the order which they have been made or show them upside down, but they'll be stuck in that order (I'm using a loop to find folders and then increase or decrease the folder number). Does anybody have any ideas on how I can make threads which get replies to the top of the list?
I thought of an order.txt file which has the thread numbers in a certain order and when a reply gets made to thread X the script should put X at the top of that list (or bottom, easy to inverse).
Suggestions are very much appreciated!
Well, while I don't agree with the wisdom of doing it this particular way, the order text file seems fine enough granted depending how often your updating your threads there may be read/write lock issues.
Another option is to check the modified time for the folders and/or posts. http://php.net/manual/en/function.filemtime.php i believe would be an appropriate function.
In reference to sorting you'd need to use a sorting function. The best ideas i can come up with is when creating your array convert the modified time to a unix timestamp and use that as the array index. May need to invert the array after to show newest first but i would think that would work. I'd suggest using the mktime function in conjunction to produce a nicely formatted date/time and then use that for the index.
An alternative is storing an array within array and doing something like this:
$threadArray = array(
array("thread" => "1", "timemodified" => "12703048849"),
array("thread" => "2", "timemodified" => "12703048842"),
array("thread" => "3", "timemodified" => "12703045349"),
array("thread" => "4", "timemodified" => "12703021449"),
);
function sortByTime($a, $b)
{
return strnatcmp($a['timemodified'], $b['timemodified']);
}
# sort
usort($threadArray, 'sortByTime');
Stick a file in each folder (1, 2, 3, etc...) that contains a line with the time that the thread was last updated (could be when it was posted if it has no replies or the time of the last reply). When it's time to display each thread, look at the time in that file and slot it into the correct position when displayed.
The reason I'd do this over creating an order.txt file is that a single file is:
Easily corrupted, meaning that you'd
lose ALL ordering info.
It is inefficient to read/rewrite a large
file everytime a post is added
You can also stick other data you might want into this text file in each folder. It's kind of like how Windows stores thumbnails in a thumbs.db file for each folder.
Pretty similar to box9, but with a different approach.
In each thread folder, make a file, let's say - random.timestamp.txt ($file = 'random.'.time().'.txt';).
Whenever there are changes within the thread, you rename this file with the new timestamp. When you're displaying threads, fetch each threads timestamp file and align them as you wish (DESC / ASC). Something like that..
I'll probably get down voted for this, but if you're not going for a relational database here, why not make the order information part of the file/folder name? So you could order by metadata that is contained as part of the file/folder name scheme (as you have started to do here) your threads directory would contain a 1_2/ (first thread, second order) 2_1/ (second thread, most recent), 3_0/ (third thread, sticky <--please forgive the feature creep) This would allow you to use the split function to get relevant metadata from the file names.
Final folder structures would vary and change on update, but might look something like this in a snapshot:
/threads/
1_2/
1.txt
2.txt
2_3/
1.txt
2.txt
3.txt
3_1/
1.txt
2.txt
Related
I tried using PHP to run 7zip to recursively extract all the zip files that a user had put inside other zip files and then delete the original zip.
The code I used worked except for a larger file (about 7gigs) that had some unusual file types (like hdr and cab files for example) where it did not fully extract the files, made duplicates of some of the ones it did, and then did not delete the original zip. The only thing I saw out of the ordinary about it was that the command prompt I ran the php file from said "Incomplete Extraction". I'm not sure why the extraction and deletion worked for every file but this one.
Any help in understanding this would be greatly appreciated!
Thank you for your time
Here is the code snippet:
$cmd_2 = "FOR /R \"$zip_file_directory\" %I IN (*.zip) DO (7z x \"%I\" -aou -o\"%~dpI\" && del \"%~fI\")";
exec($cmd_2, $out_2, $ret_2);
EDIT
Also it returned a 0 exit code. So again I have no idea what went wrong.
However looking at the $out I can see about 2700 key/value relationships in the array (Example: [2685] => Extracting Client Video\Reviewer\setup.lid)
And at the very end it says "Sub Item Errors: 5" but I can't seem to find a way to find exactly what that means.
EDIT II
I was going through the 2700 lines of code and found a few like this: "[1325] => can not open output file ...." and then has a filename.
Any idea why this is happening so rarely (It looks like these are the 5 errors) out of thousands of lines of extraction?
EDIT III
There is an article here that states that this might be a 7zip issue with firewall, can anyone confirm or deny this?
I have some questions about fopen
The first question it’s when i go for add new entry always put to the end of file and no start the file, for example:
$fp=fopen("text.dat","a");
fputs($fp,"Hello 1"."\n");
fclose($fp);
Always the results in this file show to the end:
Hello 1
Hello 2
Hello 3
And no as I want, insert the new comment to the first place for show this as:
Hello 3
Hello 2
Hello 1 ( The most old entry )
By other side my second question, for example if i have 10 users and this 10 users to the same time insert one entry or post inside this text file, it’s possible or can give me some error? Or I need use flock until save each post, which it’s the best method for no give me problems when some users want change something in the file in the same time?
There's no way to prepend the file automatically. So, it is better to store the existing contents in a temp file and then insert it in the file.
$fp=fopen("text.dat","w");
fwrite($fp,"Hello 1"."\n".fread($fp));
fclose($fp);
This will be outputting as:
Hello 3
Hello 2
Hello 1
But as far as lock is considered, I don't think it is possible, or am not the right person to answer for this.
When you write to a file it'll always append at the end. There's no workaround it which I'm aware of, but in order to achieve what you want (which is to display the lines in reverse order) you can read the lines into an array and display the array in reverse order.
As for locking, only one process can hold the lock to a file, so you don't really have to do anything cause if two users try to update the same file at the same time - only one of them will succeed - which actually creates a different problem (one of the users will lose her post). In order to work around it you should send to the backend both the original copy of the post and the new version submitted by the user, before you save the user's edit - check that the original version is updated. If it's not up-to-date it means that another user changed it meanwhile. The "user-friendly" behavior would be to return an error to the user saying that he's version is not up-to-date but also include his edits - so that he won't have to re-write everything from scratch.
For that you need a database, which is more suited for multi-user things and sorting,
Or else use a subdirectory and create every message in its own file, with a file name made up of a sortable timestamp: yyyymmddhhmmss. But then you need to prevent directory caching.
As everyone has the right to be stubborn/cut of an edge: see file_get_contents to load all the contents, and file_put_contents.
I have a file, which contains passwords/usernames:
thomas 123
john 321
What would be the best way to identify lines and add to them contact information? Right in password file I dont want store, because the size of the file matters.. I thought to add an identifier string before records, like this:
[1]
thomas 123
[2]
john 321
What do you think? It is a good way to identify lines? If yes, how I can read out line after identifier [number]?
If I can read out, then in a second file I can store contact information.
[1]
email, etc
[2]
email etc
this is a config file of an offline app, sadly I cant change the structure of that file (max. change: add an identifier before lines) or use database.
Thank you so much,
Adrian
You could use a while loop that reads every other line as your id and every other line as your username and password; however, like what #zerkms said, you're better off putting your energy into a tried and tested database.
Learning to use a database will save you time in the future so that on each project you don't have to figure out exactly how to manipulate a flat file.
Reusable solutions enable and empower you to focus on your goal and your product, whatever that may be.
As zerkms wrote in his comment to your question, you should probably use a database for that. If you don't feel comfortable with setting up a database on a server, look into SQLite (php manual) which is a file-based database which is really easy to use and setup.
If you want to stick with the text-file approach, why write your own format and parser? You could just as well use an existing format like JSON (can be parsed with json_decode) or even an INI file (use parse_ini_file).
And: Never store your text-file at a place where it's globally accessible (eg. webroot).
Supposedly the usernames in the password file are unique (otherwise it wouldn't be very useful). Assuming that's the case, why can't you leave its structure as is without adding anything to it? Then your contact file could be formatted as an INI file or JSON file as bummzack suggested with the username as the key.
You can handle this as simple as a single call to file function.
$lines = file ('passwords.txt');
After that you'll have all lines numbered from 0 to N-1.
I am using Jquery to post a value to a page which should then search a folder and its sub-folders to see where the file exists.
The start of the filename will always have something like "HAV_" and then the product code...
HAV_345GG.jpg
I need to take the posted value which is the product code and search all folders to find a match then return the location as a link ie:
http://www.mydomain.co.uk/folder/subfolder/HAV_345GG.jpg
Any help would be great.
Another option is to make use of PHPs glob function which returns an array based on a pattern match. This seems like it could be used in this case. You would need to be careful of files with similar names partially matching though such as:
HAV_123
HAV_1234
You need to create a lookup table so you can quickly find things by product code.
Create a script to rip through all the folders and index the location of the image files by product code. Cache this scripts output somewhere (db, redis memcached, etc).
Create a search script that uses the cached lookup table to find the path to the correct file.
You cache might be a PHP array such as:
array(
'ProductCode123' => array(
'/location/to/image1.jpg',
'/path/to/image2.jpg',
),
'SerialNumber12233' => array(
'/some/location/to/image1.jpg',
'/another/folder/image2.jpg',
),
);
Without this caching method you are going to find performance to be an issue if there is a lot of files and directories.
A colleague wrote a PHP script called uberloader, which does a similar thing but acts a PHP autoloader for disparate file structures such as yours in legacy projects. It is intended to autoload class files but a similar concept of hunting and caching is used.
Alright, so I've just (almost) finished my first little php script. Basically all it does is handling forms. It writes whatever the user put in to the fields of the form to a text file, then I include that text file in the index of the little page I have set up.
So, currently it writes to the beginning of the text file (but doesn't overwrite previous data). But, several users wants this list to be alphabetically sorted instead. So what I want to do is make whatever they submit fall into the list in alphabetical order.
The thing here is also that all I use in the text file are divs. The list is basically 'divided' into 3 parts. 'Title', 'Link', and 'Poster'. All I have done is positioned them with css.
So, can I sort this list (the titles, in this case) alphabetically and still have the 'link' and 'poster' information assigned the way they already are, but just with the titles sorted?
It don't use databases at all on my site, so there is no database handling at all used in this script (mainly because I'm not experienced at all in this).
I would also suggest storing the data in the file as either XML or JSON. PHP can sort the records easily and the sorting will be preserved in the file when the data is read back in.
For example
file_put_contents("/tmp/datafile",json_encode($recordset));
and when reading the file back in
$recordset = json_decode(file_get_contents("/tmp/datafile"));
edit
but seriously if you have customers and are charging them for your experience and time, use a database, there are many out there (a few mentioned already)
MySQL
sqlite
PostgreSQL
Oracle
MSSQL
If you really don't want to use a database, even a one-file database (such as sqlite), you can group the three fields using a separator such as _ and sort this single-field list
If this is a small project for some friends or something and the file shouldn't ever have more than maybe a few hundred lines, the functions you're looking for are "file" and "usort".
If you make sure each row is on its' own line, you can load the lines into an array with "file". You can sort the array using a function to compare items with the "usort" function.