View Full Version : PHP+file handling+confused???
shachi
07-09-2006, 07:21 PM
Hello everyone,
I am learnt PHP file handling and plain text database manipulation and I am trying to make a authentication system with plain text database(comma seperated values) the thing which is bugging me is that one can create a user but cannot update h(is/er) profile neither can he delete his username. I have been trying to make it work for a long time now and I finally think I cannot do it on my own. I seek for help and any help would be greatly appereciated. Thank you for your time reading this thread.:)
shachi
07-10-2006, 03:53 PM
Any help here would be greatly appereciated.:)
You haven't given enough information for anyone to help you.
shachi
07-10-2006, 04:11 PM
Ok. Here is my description. I have three pages: createuser.php, updateprofile.php and deleteuser.php. They all share a common flat file database(not quite flat) which is database.php which looks like this:
<?php exit(); ?>
#stores users in
#comma seperated
#values.
#format: username,password,email,zip,country
createuser.php looks something like this:
<html>
<head>
</head>
<body>
<form name="testform" action="testcreate.php" method="POST">
UserName:<input type="text" name="name">
Email:<input type="text" name="email">
Password:<input type="text" name="password">
Zip:<input type="text" name="zip">
Country:<input type="text" name="country">
<input type="submit">
</form>
</body>
</html>
It gets to another file testcreate.php which stores the data using post to the file database.php. testcreate.php looks like this:
<?php
$handle = fopen('database.php', 'a');
fwrite($handle, $_POST['name'].",".$_POST['password'].",".$_POST['email'].",".$_POST['zip'].",".$_POST['country']."\n");
fclose($handle);
echo "Please click <a href='login.php'>here</a> to go to the login page."
?>
This stores the data.
The deleteuser.php looks like this:
#source php.net
<?
$key = $_POST["username"];
$fc=file("database.php");
$f=fopen("database.php","w");
foreach($fc as $line)
{
if (!strstr($line,$key))
fputs($f,$line);
}
fclose($f);
?>
The $_POST["username"] comes from a page deleteuser.html.
The problem I am having is I couldn't make a script to edit the profile of the user.
I need a script(descripted I am learning PHP not copying) which could let the users update their profile in the flat file database.
I hope I was able to clear my point.
Thanks.
Well, you should create a function that loops through the lines, looks for the supplied username, reads in the information to an array (explode (http://www.php.net/explode)() will help you here), constructs a new line from that data and the new data provided, then deletes the old line and inserts the new one.
It would have been so much easier to write a demo script. :p
shachi
07-10-2006, 04:54 PM
Umm, I hate to admit it Twey but I have not yet studied about the explode() function and I wish you could give me some hints on doing so. I am just a beginner you remember??;) I can create a function that loops through the file and looks for the supplied username(it's similar to the delteuser.php isn't it??) but how do I read the information into an array and construct a new line from the data and add the new data provided and delete the old line??
EDIT: By the way I just realized the explode() contained a link. Going through it.
That's why I gave you the link :p
shachi
07-10-2006, 05:12 PM
Yep went through it. Isn't explode() something like split()??
Similar, but no regex, just a simple seperator string.
shachi
07-10-2006, 05:29 PM
Now how do I do this part??
reads in the information to an array (explode() will help you here), constructs a new line from that data and the new data provided, then deletes the old line and inserts the new one.
// Defines.
define (http://www.php.net/define)('DATABASE_FILE', 'database.php');
define (http://www.php.net/define)('SEPARATOR', ',');
define (http://www.php.net/define)('LINEBREAK', "\n");
define (http://www.php.net/define)('USERNAME', 0);
define (http://www.php.net/define)('PASSWORD', 1);
define (http://www.php.net/define)('EMAIL', 2);
define (http://www.php.net/define)('COUNTRY', 3);
define (http://www.php.net/define)('ZIP', 4);
function updateUser($ccol, $cval, $col, $val) {
$ret = 0;
$lines = file (http://www.php.net/file)(DATABASE_FILE); // Read DATABASE_FILE into $lines as an array, broken at the linebreaks.
for($i = 0; $i < count (http://www.php.net/count)($lines); ++$i) {
$cline = explode (http://www.php.net/explode)(SEPARATOR, $lines[$i]); // Read $lines[$i] into $cline as an array, broken at SEPARATOR.
if($cline[$ccol] == $cval) { // If this line matches the condition given,
$cline[$col] = $val; // set the specified column to the specified value.
$lines[$i] = implode (http://www.php.net/implode)(SEPARATOR, $cline); // Put $cline back together again, and insert it back into $lines.
++$ret;
}
}
$f = fopen (http://www.php.net/fopen)(DATABASE_FILE, 'w'); // Open the file. Truncate to zero length (basically delete the file and create a new one; if memory corruption occurs here, bye-bye database)
fwrite (http://www.php.net/fwrite)($f, implode (http://www.php.net/implode)(LINE_BREAK, $lines)); // Put the lines back together again and write them back to the database
fclose (http://www.php.net/fclose)($f);
return $ret; // Return the number of lines matched and modified
}Then, to modify the user with the username 'Twey' and set his country to "England":
updateUser(USERNAME, 'Twey', COUNTRY, 'England');Sorry for the delay, I thought I'd posted, but evidently hadn't.
shachi
07-11-2006, 07:19 AM
Never mind. Thanks for the script!!! I will try this right away. Twey By the way it'd have been a lot better if you posted it with remarks on what one line does. But never mind I'll try to figure it out myself. Thank you again.:)
There, all nicely linked and commented. :)
shachi
07-11-2006, 05:59 PM
Oh thanks, but I think I have a problem now. Either I made a mistake in installing that script or there is some problem(I think I made a mistake but I am not sure). It doesn't update the name but adds a new line before the first line of the file.
I mean that if the database.php looks like this at first:
<?php exit()?>
Shachi,test,shachibista[at]gmail[dot]com,nepal
After running that script it becomes:
<?php exit()?>
Shachi,test,shachibista[at]gmail[dot]com,nepal
I don't know what the problem is but for testing purposes I just made a new file and tried executing that script. The new file looks sth like this:
<?php
define('DATABASE_FILE', 'database_fake.php');
define('SEPARATOR', ',');
define('LINEBREAK', "\n");
define('USERNAME', 0);
define('PASSWORD', 1);
define('EMAIL', 2);
define('COUNTRY', 3);
define('ZIP', 4);
function updateUser($ccol, $cval, $col, $val) {
$ret = 0;
$lines = file(DATABASE_FILE);
for($i = 0; $i < count($lines); ++$i) {
$cline = explode(SEPARATOR, $lines[$i]);
if($cline[$ccol] == $cval) {
$cline[$col] = $val;
$lines[$i] = implode(SEPARATOR, $cline);
++$ret;
}
}
$f = fopen(DATABASE_FILE, 'w');
fwrite($f, implode("\n", $lines));
fclose($f);
return $ret;
}
updateUser(USERNAME, 'Shachi', COUNTRY, 'Nepal');
?>
Well, first let's make sure you understand what you're doing here -- your code says you does, but your text was a little vague.
updateUser(USERNAME, 'Shachi', COUNTRY, 'Nepal'); should find all users with the username "Shachi" and set their country to "Nepal." Is this what you intended?
Anyway, I've actually tested this, and it works:
<?php
define('DATABASE_FILE', 'database_fake.php');
define('SEPARATOR', ',');
define('LINEBREAK', "\n");
define('USERNAME', 0);
define('PASSWORD', 1);
define('EMAIL', 2);
define('COUNTRY', 3);
define('ZIP', 4);
function updateUser($ccol, $cval, $col, $val) {
$ret = 0;
$lines = array_unique(file(DATABASE_FILE));
for($i = 0; $i < count($lines); ++$i) {
$cline = explode(SEPARATOR, $lines[$i]);
if($cline[$ccol] == $cval) {
$cline[$col] = $val;
$lines[$i] = implode(SEPARATOR, $cline);
++$ret;
}
}
$f = fopen(DATABASE_FILE, 'w');
fwrite($f, str_replace(LINEBREAK . LINEBREAK, LINEBREAK, implode("\n", $lines)));
fclose($f);
return $ret;
}
updateUser(USERNAME, 'Shachi', COUNTRY, 'Nepal');
?>The empty lines it prepended weren't really a problem, but they were annoying, so I removed them, along with any duplicate rows found in the database.
However, for me the script worked from the start, albeit with aforementioned prepended lines, so this is no guarantee it'll work for you. Try it and see.
shachi
07-11-2006, 07:36 PM
That is pretty much what I want. :) But there is a problem that the format of the data should be constant(username,password,email,country,zip) but anyways I think I found out a way but not sure it works right.
$key = $_POST['user'];
$fc=file("database.php");
$f=fopen("database.php","w");
foreach($fc as $line)
{
if (!strstr($line,$key))
fputs($f,$line);
}
fclose($f);
$f=fopen("database.php","a");
fwrite($f, $_POST['user'].','.$_POST['pass'].','.$_POST['email'].','.$_POST['country'].','.$_POST['zip']."\n");
fclose($f);
What this does is finds the line with the username(which is unique through out the file) and then deletes that line and add a line at the end of the file with the username(will be submitted with the update form) password(is a must for updating profile) and country and zip will be also submitted with the form submission. I still need to write a conditional statement to not to let the user if the submitted data matches the one in the file. But what do you think Twey??
shachi
07-13-2006, 02:49 PM
At first I thought the script I supplied in my earlier post would work but now I have a great problem because if the user doesn't supply anything for a certain value for e.g if a user wants to update just his password then it won't work the file will just append the data the user entered. Twey, or anyone else please help if anyone knows a fix for this problem. HELP!!!!
But what do you think Twey??I think that what you say it would do is exactly the same as what mine does, except for the new line :p
But there is a problem that the format of the data should be constant(username,password,email,country,zip)Er, it is in my code. If you want to change the order, move the defines around.
shachi
07-13-2006, 04:55 PM
Er, it is in my code. If you want to change the order, move the defines around.
Move the defines around?? I couldn't get you. If I place the defines in some other order will it affect the code?? Please forgive me for my silly questions but I am just a newbie. And can you instruct me on how to make the function to accept more arguements(other than username and country).
EDIT: Never mind, I found out just place two other attribute vars in the function like function($test1,$test2) and place this between the if condition $cline[$test1] = $test2. Thanks Twey for all your help time and support.:)
Try this. I'm not too sure of it, though, since it uses quite a few functions I'm not all that familiar with.
<?php
define('DATABASE_FILE', 'database_fake.php');
define('SEPARATOR', ',');
define('LINEBREAK', "\n");
define('USERNAME', 0);
define('PASSWORD', 1);
define('EMAIL', 2);
define('COUNTRY', 3);
define('ZIP', 4);
function updateUser() {
$ret = 0;
$lines = array_unique (http://www.php.net/array-unique)(file[/file](DATABASE_FILE));
$argv = [url=http://www.php.net/func-get-args]func_get_args (http://www.php.net/file)();
$conditions = array();
$changes = array();
for($i = 0; $i < count (http://www.php.net/count)($argv) && $argv[$i] != SEPARATOR; $i += 2)
$conditions[$argv[$i]] = $argv[$i + 1];
for(++$i; $i < count($argv); $i += 2)
$changes[$argv[$i]] = $argv[$i + 1];
for($i = 0; $i < count($lines); ++$i) {
$cline = explode (http://www.php.net/explode)(SEPARATOR, $lines[$i]);
$changeThisLine = false;
foreach($conditions as $k => $v)
if($changeThisLine = ($cline[$k] == $v)) continue;
foreach($changes as $k => $v) {
$cline[$k] = $v;
++$ret;
}
$f = fopen(DATABASE_FILE, 'w');
fwrite($f, str_replace(LINEBREAK . LINEBREAK, LINEBREAK, implode("\n", $lines)));
fclose($f);
return $ret;
}
updateUser(USERNAME, 'Shachi', COUNTRY, 'nepal', SEPARATOR, COUNTRY, 'Nepal', EMAIL, 'some.new@email-address.com');
?>Note that each argument works as an "or" operand.
shachi
07-13-2006, 06:40 PM
Twey, it gives a Parse error: parse error, unexpected $ in /var/www/html/shachi/php/test/testup.php on line 38
shachi
07-14-2006, 02:29 PM
Twey: Are you around??
shachi
07-15-2006, 11:55 AM
Any help here??
shachi
07-17-2006, 12:02 PM
Any Help Here???
Whoops, typo. Try this one:
<?php
define('DATABASE_FILE', 'database_fake.php');
define('SEPARATOR', ',');
define('LINEBREAK', "\n");
define('USERNAME', 0);
define('PASSWORD', 1);
define('EMAIL', 2);
define('COUNTRY', 3);
define('ZIP', 4);
function updateUser() {
$ret = 0;
$lines = array_unique([url=http://www.php.net/file]file[/file](DATABASE_FILE));
$argv = func_get_args();
$conditions = array();
$changes = array();
for($i = 0; $i < count($argv) && $argv[$i] != SEPARATOR; $i += 2)
$conditions[$argv[$i]] = $argv[$i + 1];
for(++$i; $i < count($argv); $i += 2)
$changes[$argv[$i]] = $argv[$i + 1];
for($i = 0; $i < count($lines); ++$i) {
$cline = explode(SEPARATOR, $lines[$i]);
$changeThisLine = false;
foreach($conditions as $k => $v)
if($changeThisLine = ($cline[$k] == $v)) continue;
foreach($changes as $k => $v)
$cline[$k] = $v;
++$ret;
}
$f = fopen(DATABASE_FILE, 'w');
fwrite($f, str_replace(LINEBREAK . LINEBREAK, LINEBREAK, implode("\n", $lines)));
fclose($f);
return $ret;
}
updateUser(USERNAME, 'Shachi', COUNTRY, 'nepal', SEPARATOR, COUNTRY, 'Nepal', EMAIL, 'some.new@email-address.com');
?>
shachi
07-17-2006, 01:55 PM
Twey, It didn't work.:(
But I tried to update the code from liro from the other post and came up with something like this:
(For test purposes used online.txt with | as separator the original database will have ,)
<?php
function replaceLine($f, $etsi, $first, $second) {
if(!file_exists($f)) {
die("Sorry the file " . $f . " could not be found.");
} else {
$filearr = file($f);
$sisalto;
for($i = 0; $i < count($filearr); $i++) {
list($id, $nimi, $passu) = explode("|", $filearr[$i]);
if($first == ""){
$first = $nimi;
}
if($second == ""){
$second = $passu;
}
if($id == $etsi) {
$sisalto .= $id . "|" . $first . "|" . $second . "\n";
} else {
$sisalto .= $filearr[$i];
}
}
$fi = fopen($f, "w");
fwrite($fi, $sisalto);
fclose($fi);
}
}
replaceLine("online.txt", "Test7", "", "");
?>
But it has a problem that if the values are not supplied it replaces the second and third values with the second and third values of the first line. I need a function to loop through every line of the array searching for a key and then give the index number of the array. So far I have made something like this:
<?php
$loopIndex = 0;
$test = array('Test0','Test1','Test2','Test3');
#$test = file("online.txt");
while($test[$loopIndex] != "Test4|test5|test6" && $loopIndex < 4){
$loopIndex++;
}
if($loopIndex < 4){
echo "Found supplied value at index ".$loopIndex;
}
#echo $test[3];
?>
online.txt looks something like this:
Test1|test2|test3
Test4|test5|test6
Test7|test8|test9
Test10|test11|test12
But as soon as I uncomment the $test = file("online.txt"); it shows nothing.
I have tried my best but could not come up with a suitable code. I have almost lost.
Any ideas??
Twey, It didn't work.You ought to know by now not to say "it didn't work." :) What went wrong?
shachi
07-17-2006, 05:30 PM
Oops!! Sorry. It doesn't update the file. I have been trying to fix it but unforutnately I don't have much brain about PHP. :(
This is tested:
<?php
define('DATABASE_FILE', 'database_fake.php');
define('SEPARATOR', ',');
define('LINEBREAK', "\n");
define('USERNAME', 0);
define('PASSWORD', 1);
define('EMAIL', 2);
define('COUNTRY', 3);
define('ZIP', 4);
function updateUser() {
$ret = 0;
$lines = array_unique(file(DATABASE_FILE));
$argv = func_get_args();
$conditions = array();
$changes = array();
for($i = 0; $i < count($argv) && $argv[$i] !== SEPARATOR; $i += 2)
$conditions[$argv[$i]] = $argv[$i + 1];
for(++$i; $i < count($argv); $i += 2)
$changes[$argv[$i]] = $argv[$i + 1];
for($i = 0; $i < count($lines); ++$i) {
$cline = explode(SEPARATOR, $lines[$i]);
$changeThisLine = false;
foreach($conditions as $k => $v)
if(!($changeThisLine = ($cline[$k] == $v))) break;
foreach($changes as $k => $v)
$cline[$k] = $v;
$lines[$i] = implode(SEPARATOR, $cline);
++$ret;
}
$f = fopen(DATABASE_FILE, 'w');
fwrite($f, str_replace(LINEBREAK . LINEBREAK, LINEBREAK, implode("\n", $lines)));
fclose($f);
return $ret;
}
updateUser(USERNAME, 'Shachi', COUNTRY, 'nepal', SEPARATOR, COUNTRY, 'NePaL', EMAIL, 'some.new@email-address.com');
?>It works, but not with the line of PHP code in the file. You should remove it.
shachi
07-17-2006, 07:48 PM
Twey, it edits all the user's information. For example if the database_fake.php is like this:
Test,test,test@test.com,sweden
testuser,test,test@user.com,uk
Then after executing the PHP script it changes the values to :
Test,test,some.new@email-address.com,NePaL
testuser,test,some.new@email-address.com,NePaL
And by the way if I remove the <?php exit()?> lines then anyone would be able to view the database(sure I could encrypt the password with md5 hash but what about the email addresses??They'd be a great source for spambots).
I am sorry to make you write bunch of codes and take up your time but I need help and I cannot do it myself. You are more experienced than me.
Not tested thoroughly enough, obviously :) How about this?
<?php
define('DATABASE_FILE', 'database_fake.php');
define('SEPARATOR', ',');
define('LINEBREAK', "\n");
define('USERNAME', 0);
define('PASSWORD', 1);
define('EMAIL', 2);
define('COUNTRY', 3);
define('ZIP', 4);
function updateUser() {
$ret = 0;
$lines = array_unique(file(DATABASE_FILE));
$argv = func_get_args();
$conditions = array();
$changes = array();
for($i = 0; $i < count($argv) && $argv[$i] !== SEPARATOR; $i += 2)
$conditions[$argv[$i]] = $argv[$i + 1];
for(++$i; $i < count($argv); $i += 2)
$changes[$argv[$i]] = $argv[$i + 1];
for($i = 0; $i < count($lines); ++$i) {
$cline = explode(SEPARATOR, $lines[$i]);
$changeThisLine = true;
foreach($conditions as $k => $v)
if($cline[$k] != $v)
$changeThisLine = false;
if(!$changeThisLine) continue;
foreach($changes as $k => $v)
$cline[$k] = $v;
$lines[$i] = implode(SEPARATOR, $cline);
++$ret;
}
$f = fopen(DATABASE_FILE, 'w');
fwrite($f, str_replace(LINEBREAK . LINEBREAK, LINEBREAK, implode("\n", $lines)));
fclose($f);
return $ret;
}
?>
And by the way if I remove the <?php exit()?> lines then anyone would be able to view the database(sure I could encrypt the password with md5 hash but what about the email addresses??They'd be a great source for spambots).There are many different ways to accomplish this. For a start, that file is not referenced anywhere that's visible to the user, so it'd have to be one lucky spammer to stumble across the file (especially if you give it a slightly less obvious name).
If that's not enough for you (and it shouldn't be, really) a simple solution is to move the file outside the web root.
shachi
07-17-2006, 09:05 PM
Twey, this script has the same problem, it doesn't update the file.
Currently my page looks like this:
<?php
define('DATABASE_FILE', 'database.php');
define('SEPARATOR', ',');
define('LINEBREAK', "\n");
define('USERNAME', 0);
define('PASSWORD', 1);
define('EMAIL', 2);
define('COUNTRY', 3);
define('ZIP', 4);
function updateUser() {
$ret = 0;
$lines = array_unique(file(DATABASE_FILE));
$argv = func_get_args();
$conditions = array();
$changes = array();
for($i = 0; $i < count($argv) && $argv[$i] !== SEPARATOR; $i += 2)
$conditions[$argv[$i]] = $argv[$i + 1];
for(++$i; $i < count($argv); $i += 2)
$changes[$argv[$i]] = $argv[$i + 1];
for($i = 0; $i < count($lines); ++$i) {
$cline = explode(SEPARATOR, $lines[$i]);
$changeThisLine = true;
foreach($conditions as $k => $v)
if($cline[$k] != $v)
$changeThisLine = false;
if(!$changeThisLine) continue;
foreach($changes as $k => $v)
$cline[$k] = $v;
$lines[$i] = implode(SEPARATOR, $cline);
++$ret;
}
$f = fopen(DATABASE_FILE, 'w');
fwrite($f, str_replace(LINEBREAK . LINEBREAK, LINEBREAK, implode("\n", $lines)));
fclose($f);
return $ret;
}
updateUser(USERNAME, 'Shachi', COUNTRY, 'nepal', SEPARATOR, COUNTRY, 'Nepal', EMAIL, 'some.new@email-address.com');
?>
and my db file looks like this:
Test,test,test@test.com
testuser,test,test@user.com
Shachi,test,shachibista@gmail.com,nepal
:(:'(
Aha, seems we had a few extraneous linebreaks hanging around:
<?php
define('DATABASE_FILE', 'database.php');
define('SEPARATOR', ',');
define('LINEBREAK', "\n");
define('USERNAME', 0);
define('PASSWORD', 1);
define('EMAIL', 2);
define('COUNTRY', 3);
define('ZIP', 4);
function updateUser() {
$ret = 0;
$lines = array_unique(file(DATABASE_FILE));
$argv = func_get_args();
$conditions = array();
$changes = array();
for($i = 0; $i < count($argv) && $argv[$i] !== SEPARATOR; $i += 2)
$conditions[$argv[$i]] = $argv[$i + 1];
for(++$i; $i < count($argv); $i += 2)
$changes[$argv[$i]] = $argv[$i + 1];
for($i = 0; $i < count($lines); ++$i) {
$cline = explode(SEPARATOR, str_replace(LINEBREAK, '', $lines[$i]));
if(count($cline) < 2) continue;
$changeThisLine = true;
foreach($conditions as $k => $v)
if($cline[$k] != $v)
$changeThisLine = false;
if(!$changeThisLine) continue;
foreach($changes as $k => $v)
$cline[$k] = $v;
$lines[$i] = implode(SEPARATOR, $cline);
++$ret;
}
$f = fopen(DATABASE_FILE, 'w');
fwrite($f, str_replace(LINEBREAK . LINEBREAK, LINEBREAK, implode("\n", $lines)));
fclose($f);
return $ret;
}
updateUser(USERNAME, 'Shachi', COUNTRY, 'nepal', SEPARATOR, COUNTRY, 'Nepal', EMAIL, 'some.new@email-address.com');
?>The syntax is, for example:
updateUser(condition_column_1, condition_value_1, condition_column_2, condition_value_2, SEPARATOR, column_1, new_value_1, column_2, new_value_2)... which would be similar to the SQL:
UPDATE table SET column_1=new_value_1, column_2=new_value_2 WHERE condition_column_1=condition_value_1 AND condition_column_2=condition_value_2;
shachi
07-18-2006, 07:09 AM
Twey it does what I want. Can I add more arguements?? like zip, 'somevalue' ??Thanks.
Yes, you can add as many column/value pairs as you like.
shachi
07-18-2006, 09:01 AM
Then it works just fine, but I have another question, Can the function have only one arguement instead of two and will it also work fine??
For each column to be checked or altered, it needs two arguments: a column number (provided by the defines) and a value. You should be able to miss out all the arguments on either side of the SEPARATOR without problems, though.
shachi
07-18-2006, 06:31 PM
Thank you very much Twey, for all your support and help and time. It worked like a dream.
Thank you again!!!:D
No problem -- I even learnt a bit in the process. :)
Powered by vBulletin® Version 4.2.2 Copyright © 2021 vBulletin Solutions, Inc. All rights reserved.