Alfie B
Alfie B

Reputation: 172

How do I replace 1 value within a row in a CSV file using php?

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!");
}
?>

Upvotes: 5

Views: 9258

Answers (3)

cram2208
cram2208

Reputation: 416

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,

Upvotes: 3

acontell
acontell

Reputation: 6932

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.

Upvotes: 10

Richard87
Richard87

Reputation: 1622

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!

Upvotes: 0

Related Questions