Royce
Royce

Reputation: 45

Unable to unset value from array

I been trying to unset a value from an array without success, I'm trying to be able to edit values from a CSV file. When I click edit it should open the values load it locally unset it and re save the array with the new value. My problem is that the all the values are being added twice along with the new edit value.

This is my edit function

class edit extends index{
    public function GET(){

    $Remail = ($_REQUEST['email']);
    $filename = 'testfile.csv';
    $lines    = file($filename); 
    foreach($lines as $info) {
            $CSVString = explode(',', $info);
            $this->email = trim(explode("=", $CSVString[0])[1]);

            if ($Remail === $this->email){
                    $this->Fname = trim(explode("=", $CSVString[1])[1]);
                    $this->Lname = trim(explode("=", $CSVString[2])[1]);
                    unset($CSVString[0]);


            }
            $this->person = array('Email'=>$this->email,'FirstName' =>$this-      >Fname, 'LastName' =>$this->Lname);
            $this->save($this->person);

            }


   echo  '<form action="index.php?page=adduser" method="POST">
          <label for="email">Email:</label></br>
          <input type="text" name="Email" value="' . $Remail . '"></br>
      <label for="fname">First Name:</label></br>
      <input type="text" name="Fname" value="' . $this->Fname . '"></br>
      <label for="lname">Last Name:</label></br>
      <input type="text" name="Lname" value="' . $this->Lname . '"></br>
      <input type="submit">
  </form>';
    }

this is my save function

public function save($arr){
    $filename = 'testfile.csv';
    $myfile = fopen($filename, "a+") or die("Unable to open file!");
    foreach($arr as $key => $value){
        $new [] = $key.'='.$value;
        $final =  implode(",", $new);
        }
    fwrite($myfile, $final.PHP_EOL);
    fclose($myfile);
}

And this is the adduser that the form is calling

class adduser extends index {
public function GET(){
include('add.html');
  }

public function POST($Fname, $Lname, $Email){
    $this->Fname = $Fname;
    $this->Lname = $Lname;
    $this->Email = $Email; 
    $this->person = array('Email'=>$this->Email,'FirstName' =>$this->Fname, 'LastName' =>$this->Lname);
    $this->save($this->person);

Upvotes: 0

Views: 147

Answers (1)

Ultimater
Ultimater

Reputation: 4738

Let's say you visit index.php?page=edit&[email protected]. I understand you then want to consult your CSV file and pull up this user's data and display their first and last name in a form you can edit and submit. The problem, however, is that you're submitting to index.php?page=adduser which adds the user, not edit it. I see you have two classes edit and adduser. Just as your adduser class has a GET() and POST() method, you should also have a GET() and POST() method for your edit class. The reason you're seeing duplicate data is because your edit class's GET() method is actually calling save() when there's no data to be saving in the first place. And it won't edit the data either, it will reference your $this->Fname and $this->Lname for each loop, which I assume is not set in the first place. Thus you end up appending a bunch of rows to your CSV file with the correct emails but with the same FirstName and LastName for each row, thus corrupting your data.

In terms of a solution here, simply don't call $this->save($this->person); from your edit's GET() method. Update the form to submit to the correct page:
<form action="index.php?page=edit" method="POST">
Also add a reference to the user's email as a hidden field under a different key, in case the user wants to change their email:
echo '<input type="hidden" name="oldemail" value="'.htmlentities($Remail).'">';
(yes, make sure to always escape the user's input when displaying it in HTML)

Then create a new POST() method in your edit class with the logic:

public function POST($p_oldEmail, $p_Fname, $p_Lname, $p_Email)
{
  $filename = 'testfile.csv';
  $lines = file($filename) or die("Unable to open file!");;
  $out = '';
  foreach($lines as $info)
  {
    $fields = explode(',', $info);
    $email=trim(explode("=", $fields[0])[1]);
    if($email === $p_oldEmail)
    {
      $record=array('Email'=>$p_Email,'FirstName'=>$p_Fname, 'LastName'=>$p_Lname); 
      $new=array();
      foreach($record as $key => $value)
      {
        $new[] = $key.'='.$value;
      }
      $out.=implode(",", $new).PHP_EOL;
    }else{
      $out.=$info;
    }
  }
  $myfile = fopen($filename, "w") or die("Unable to open file!");
  fwrite($myfile, $out);
  fclose($myfile);
}

(Note that the above is untested, you may have to make a slight adjustment to it)

In the future, I'd advise using fgetcsv() for parsing a CSV file one line at a time or str_getcsv for parsing an entire CSV file represented as a string in one chuck. And fputcsv for writing a line to a CSV file. Using these functions ensures proper escaping so your CSV file doesn't get corrupted if someone enters unexpected input. Although if someone enters a new line into a field, even if escaped properly, if you're reading your CSV file line by line, regardless of the new line being between quotes, then you'll run into an issue with PHP-designed functions which read a file one line at a time without caring if that line is between quotes. So if you need to preserve new lines which users might enter, I'd suggest converting them to their HTML entity equivalents when storing them in the CSV file. But if you are serious about these kind of things, you should really be using a database rather than a CSV file.

Upvotes: 1

Related Questions