Jump to content
xisto Community
Sign in to follow this  
vujsa

Php Access Log In Reverse Order Request For Help.

Recommended Posts

So I need help getting data entered into my log correctly. I want the newest entry to be at the beginning (top) of the log instead of at the end (bottom).

 

Here's what I have:

<?phpfunction access_log(){  // Enter data in usage log.	$filename = "access.log";	$entry = gmdate("M d, Y H:i:s T").": ". getenv("REMOTE_ADDR").": ". getenv("HTTP_USER_AGENT")." \n";	fwrite(fopen($filename, "a"), $entry);	fclose(fopen($filename, "a"));}  //  End function access_log()?>

And it outputs:

Mar 29, 2005 07:57:16 GMT Standard Time: 192.168.1.1: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)

Mar 29, 2005 07:57:40 GMT Standard Time: 192.168.1.1: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)

Mar 29, 2005 07:58:03 GMT Standard Time: 192.168.1.1: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)

Mar 29, 2005 08:02:01 GMT Standard Time: 192.168.1.1: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)

Mar 29, 2005 08:02:04 GMT Standard Time: 192.168.1.1: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)

Mar 29, 2005 08:02:07 GMT Standard Time: 192.168.1.1: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)

Mar 29, 2005 08:02:09 GMT Standard Time: 192.168.1.1: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)

Notice how the newest entry is at the bottom.

 

I need the data to read like this:

Mar 29, 2005 08:02:09 GMT Standard Time: 192.168.1.1: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)

Mar 29, 2005 08:02:07 GMT Standard Time: 192.168.1.1: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)

Mar 29, 2005 08:02:04 GMT Standard Time: 192.168.1.1: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)

Mar 29, 2005 08:02:01 GMT Standard Time: 192.168.1.1: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)

Mar 29, 2005 07:58:03 GMT Standard Time: 192.168.1.1: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)

Mar 29, 2005 07:57:40 GMT Standard Time: 192.168.1.1: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)

Mar 29, 2005 07:57:16 GMT Standard Time: 192.168.1.1: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)

 

I've tried:

fwrite(fopen($filename, "r+"), $entry);
Set pointer to the beginning.

But that erases the first line when a new entery is added.

 

Please let me know how to adjust the code to insert an entry at the beginning.

 

Thanks, :)

vujsa

Share this post


Link to post
Share on other sites
<?phpfunction access_log(){  // Enter data in usage log.$filename = "access.log";$entry = gmdate("M d, Y H:i:s T").": ". getenv("REMOTE_ADDR").": ". getenv("HTTP_USER_AGENT")." \n";if (!file_exists($filename)) touch($filename);$fh = fopen($filename, "r");$fcontent = fread($fh, filesize($filename));$towrite = $entry.$fcontent;$fh22 = fopen($filename, 'w+');fwrite($fh2, $towrite);fclose($fh);fclose($fh2);}  //  End function access_log()

There ya go :)

Share this post


Link to post
Share on other sites

Hey thanks Muddyboy.

 

I was afraid I'd have to do it that way. I was hoping that there was a pointer I didn't know about that would simply insert an entry before instead of overwritting the first line.

 

Just to make sure I'm reading this correctly and well recap for those that may have trouble reading it;

Create a new entry and assign the variable $entry to it

Open the file for use or create a new file if none exists.

Read the current log and assign the variable $content to it.

Create the new log as $entry + $content and assign the variable $towrite to it.

Write the variable $towrite to the file.

Close the file

Thanks a lot,

vujsa :)

Share this post


Link to post
Share on other sites

Yer i don't think there is a way to add it too the top, if there is i dont know it :(.You could on loading the file put the file into an array and reverse the array.I remember seeing a function for thatYour recap is right ;)Although it proberly would be much better to use a mysql database, but you cant always have access to a database :)

Share this post


Link to post
Share on other sites

Although it proberly would be much better to use a mysql database, but you cant always have access to a database :(

<{POST_SNAPBACK}>


Well, MySQL seemed like overkill for such a simple log file. But yes, you're right, sorting and viewing the data would be better in MySQL. Maybe the reason PHP is lacking a pointer to do what I wanted is because PHP was designed to work with database engines like MySQL. Of course, the reason I didn't know how to manipulate a simple text file was because I learned PHP with MySQL. :)

 

Thanks for the input.

 

vujsa

Share this post


Link to post
Share on other sites

I just wanted to fix up the above a bit and make it more functional with more error checking and using the global function $_SERVER instead of getenv, since it works better.

<?phpfunction access_log($log, $new_entry){	if(!file_exists($log))  touch($log);	if(!$fh = @fopen($log, 'r'))  die('Error: Failed to open file for reading.');	$old_entry = fread($fh, filesize($log));	fclose($fh);	$new_log = $new_entry . $old_entry;	if(!$fh2 = @fopen($log, 'w'))  die('Error: Failed to open file for writing.');	fwrite($fh2, $new_log, strlen($new_log));	fclose($fh2);}$filename = 'access.log';$entry = gmdate('M d, Y H:i:s T') . ': ' . $_SERVER['REMOTE_ADDR'] . ': ' . $_SERVER['HTTP_USER_AGENT'] . "\n";access_log($filename, $entry);?>

Just to explain it:

We'll skip the function for now and start with our filename and entry, this declares the name of our file and the new data to be inputted, which is a timestamp, IP address and browser agent information. This information then gets sent off in our function.

Our function access_log that will accept two inputs, the filename and the new data to be entered in.

We check if the file exists, if not we create it.

We then open the file for reading, if it fails, we exit the program leaving a message about it not being able to be opened for reading, if the error suggests it's reading we know where it's failing at for debugging.

We then store our old entries by reading it up to the last byte into a string.

We now close the handler since we no longer need to have the file opened.

We now create a new string using our new data and adding onto it the old data from the string we stored. If you're concerned about memory storage, we could unset the old_entry variable now that we've stored it in new_log.

Now we open a file for writing, and check whether it opens or not, if not, we exit the programing stating that the file could not be opened for writing, the error suggests it's the writing, so we know where it's failing if we need to debug the code.

We then write the new_log into our file, by using the new file handler we use for writing, we also state the length of what we're writing, not necessarily needed, but for binary safe methods, it is, and if you make this a habit, you'll not be wrong for whatever method you do use.

We then finish up by closing the function, it returns back to where the script left off, since there's nothing more left, the script has finished.

I too don't know of any other way of writing to the beginning of a file without overwriting it. Thought maybe writing a new file and adding the old file onto the end of it, but it's just the same as above without the extra file, also thought maybe a pattern match and replace method, but again, you'll be overwriting while still appending the old data on the end.

If anyone does come up with a better method, or some ideas that could work, It would be good to know.

Cheers,


MC

Share this post


Link to post
Share on other sites

Sorry vujsa, but I checked and rechecked the PHP documentation for you and couldn't find anything. THe method of opening files used for what you are talking about is the "random method" (that isn't what the "random" method was designed for, but it can be used for that) and PHP won't open files in random.

Share this post


Link to post
Share on other sites

Same code, different method, overboard with checking for problems.

Also, decided to remove adding the file if not found, due to the new file being created, it would be owned by the server's username than your user, which means if it's not owned by you, you'll have problems, you should instead manually create this file yourself and set the permissions.

Also checked whether the file is readabe/writable, if not you'll need to set permissions yourself as well.

Decided to change the function name to something more appropriate too and also display a success message when completed.

Changed the method, by reading the file in as an array too.

Similar code, overboard fail checking, same results.

<?phpfunction prepend($file, $data){	if(!is_writable($file) || !is_readable($file))  if(!file_exists($file)) 	 die('Error: File not found (create file)');  if(!chmod($file, 0666)) 	 die('Error: File not readable/writable (chmod 0666)');	if(!$old_data = file($file))  die('Error: Storing array of file');	if(!$fh = fopen($file, 'w'))  die('Error: Opening file for writing');	if(!fwrite($fh, $data, strlen($data)))  die('Error: Writing to file');	foreach($old_data as $value)  if(!fwrite($fh, $value, strlen($value))) 	 die('Error: Restoring old data');	if(!fclose($fh))  die('Error: Closing handler');}$filename = 'access.log';$entry = gmdate('M d, Y H:i:s T') . ': ' . $_SERVER['REMOTE_ADDR'] . ': ' . $_SERVER['HTTP_USER_AGENT'] . "\n";prepend($filename, $entry);echo 'Updating file successful';?>

I think PHP5 is more promising, and will definitely lessen the amount of code, but uncertain about the prepending to files, it still seems this is a problem.

Things that could be worked on is the type of entry data, checking the data, trimming spaces, escaping slashes, making sure that it is reading to the end of line, etc. Could possibly break it down into more functions, or even turn it into a class.

Cheers,


MC

Share this post


Link to post
Share on other sites

Wow mastercomputers,I wasn't expecting so much information. Thanks for the hard work. Iwas surprised that you hadn't replied to my post sooner. I know you're a fan of PHP. The first post you had is very similar to what I actually coded. Great minds I guess.I simplified my example problem in order to avoid getting lost in variables. My log function actually passes about ten arguments. Actually, I learned something really useful here. The touch() function. It reduced my code considerably. Again, thanks for the information. It gives me ideas for other text files and logs. also, I'm going to replace my getenv with $_SERVER as you suggested. vujsa

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×
×
  • Create New...

Important Information

Terms of Use | Privacy Policy | Guidelines | We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.