5

So this is my very simple and basic account system (Just a school project), I would like the users to be able to change their password. But I am unsure on how to just replace the Password value within a row keeping all the other values the same.

CSV File:

ID,Username,Email,DateJoined,Password,UserScore,profilePics
1,Test,[email protected],03/12/2014,Test,10,uploads/profilePics/Test.jpg
2,Alfie,[email protected],05/12/2014,1234,136,uploads/profilePics/Alfie.png

PHP: ("cNewPassword" = confirm new password)

<?php
session_start();
if(empty($_POST['oldPassword']) ||  empty($_POST['newPassword']) || empty($_POST['cNewPassword'])) {
    die("ERROR|Please fill out all of the fields.");
} else {
    if($_POST['newPassword'] == $_POST['cNewPassword']) {
        if ($_POST['oldPassword'] == $_SESSION['password']) {

            $file = "Database/Users.csv";
            $fh = fopen($file, "w");
            while(! feof($file)) {
                $rows = fgetcsv($file);
                if ($rows[4] == $_POST['oldPassword'] && $rows[1] == $_SESSION['username']) {
                    //Replace line here
                    echo("SUCCESS|Password changed!");
                } 
            }
            fclose($file);
        }
        die("ERROR|Your current password is not correct!");
    }
    die("ERROR|New passwords do not match!");
}
?>

3 Answers 3

10

You'll have to open file in read mode, open a temporary one in write mode, write there modified data, and then delete/rename files. I'd suggest trying to set up a real DB and work using it but if you're going for the csv, the code should look like more or less like this:

$input = fopen('Database/Users.csv', 'r');  //open for reading
$output = fopen('Database/temporary.csv', 'w'); //open for writing
while( false !== ( $data = fgetcsv($input) ) ){  //read each line as an array

   //modify data here
   if ($data[4] == $_POST['oldPassword'] && $data[1] == $_SESSION['username']) {
      //Replace line here
      $data[4] = $_POST['newPassword'];
      echo("SUCCESS|Password changed!");
   }

   //write modified data to new file
   fputcsv( $output, $data);
}

//close both files
fclose( $input );
fclose( $output );

//clean up
unlink('Database/Users.csv');// Delete obsolete BD
rename('Database/temporary.csv', 'Database/Users.csv'); //Rename temporary to new

Hope it helps.

Sign up to request clarification or add additional context in comments.

1 Comment

Nice solution! I've implemented it, but I didn't want to remove original file, so, instead of 2 last code strings I've written: file_put_contents('Database/Users.csv', file_get_contents('Database/temporary.csv')); unlink('Database/temporary.csv');
3

My suggestion is a little function of mine which will turn your database data into an array which you can modify and then return to original state:

With this set of function, you simply have to precise how each row/row data are separated.

function dbToArray($db, $row_separator = "\n", $data_separator = ",") {
    // Let's seperator each row of data.
    $separate = explode($row_separator, $db);

    // First line is always the table column name:

    $table_columns =
    $table_rows = array();

    foreach ($separate as $key => $row) {
        // Now let's get each column data out.
        $data = explode($data_separator, $row);

        // I always assume the first $row of data contains the column names.
        if ($key == 0)
            $table_columns = $data;
        else if ($key > 0 && count($table_columns) == count($data)) // Let's just make sure column amount matches.
            $table_rows[] = array_combine($table_columns, $data);
    }


    // Return an array with columns, and rows; each row data is bound with it's equivalent column name.
    return array(
        'columns' => $table_columns,
        'rows' => $table_rows,
    );
}

function arrayToDb(array $db, $row_separator = "\n", $data_separator = ",") {
    // A valid db array must contain a columns and rows keys.
    if (isset($db['columns']) && isset($db['rows'])) {
        // Let's now make sure it contains an array. (This might too exagerated of me to check that)
        $db['columns'] = (array) $db['columns'];
        $db['rows'] = (array) $db['rows'];

        // Now let's rewrite the db string imploding columns:
        $returnDB = implode($data_separator, $db['columns']).$row_separator;

        foreach ($db['rows'] as $row) {
            // And imploding each row data.
            $returnDB .= implode($data_separator, $row).$row_separator;
        }

        // Retunr the data.
        return $returnDB;
    }

    // Faaaaaaaaaaaail !
    return FALSE;
}

Let's just point out I tried these with your db example, and it works even when tested on it's own results such as : dbToArray(arrayToDb(dbToArray())) multiple times.

Hope that help. If I can be clearer don't hesitate. :)

Cheers,

Comments

0

You need a 3 step process to do this (create 3 loops, could be optimized to 1 or 2 loops):

  1. Load the relevant data to memory
  2. Update the desired data
  3. Save the data to the file

Good luck! :)

PS. Also your passwords should never been stored in clear text, wether in memory(session) or on disk(csv), use a hasing function!

3 Comments

Ok thanks, could you explain how to go about doing that please?
create 3 loops, one for each step, 1. to load the data into an array, then 2. find the field to update. And in the end, 3. loop trough the array to write the updated csv to file, since it is a school project I dont know how much to give you :P
Pleas look into password hashing - PHP is actually strong in this area and has some great solutions. See php.net/manual/en/faq.passwords.php#faq.passwords.bestpractice for more details

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.