Search code examples
phpcsvzend-framework2

How to Display CSV file content in Controller as an Array?


I am trying to display CSV data to array or something as an output using Zend Framework 2

I have created "hello world" module and the controller calls works fine.

CSV File location is data/csv/Foo.csv

Below is my controller:

public function indexAction()
{
  $filename = 'data/csv/Foo.csv';
  $useFirstRecordAsHeader = true;
  $delimiter = ',';
  $enclosure = '"';
  $escape = '\\';
  $this->file = new SplFileObject($filename);
  $this->file->setFlags(SplFileObject::READ_CSV | SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY | SplFileObject::DROP_NEW_LINE);

  $this->file->setCsvControl($delimiter, $enclosure, $escape);

  $this->useFirstRecordAsHeader = $useFirstRecordAsHeader;

   return $this;
    
}

But right now I am getting the error:

SplFileObject::__construct(csv/Foo.csv): failed to open stream: No such file or directory

My CSV file is in the same folder controller/csv/Foo.csv

How to read a CSV file content and display as output array or any other format? I want to do it using Zend Framework 2 only.


Solution

  • You are trying to open $this->file = new SplFileObject('csv/Foo.csv');, since you are using a relative path, on execution time that wont resolve to the folder where your controller is at (it will probably resolve to [yourprojectroot]/csv/Foo.csv).

    If you really wanted to store this csv in controller/csv, you should use something like:

     $this->file = new SplFileObject(dirname(__FILE__) . '/csv/Foo.csv');
    

    But, saving that csv there is bad for a several reasons. First you'd need to grant write permission to your webserver to be able to write in that directory, and you'd be fundamentally messing up with your data/code structure (data and code shouldn't reside together, but in easily separated silos).

    Better, create a folder "data" and and another folder "csv" in your projects directory, give your webserver permission to write there (chmod || chown, other methods), and do something like:

     $file = 'data'. DIRECTORY_SEPARATOR . 'csv' . DIRECTORY_SEPARATOR . 'Foo.csv' ;
     $this->file = new SplFileObject($file );
    

    Besides that, I'm not sure what you are returning actually makes sense. Try something like:

    public function indexAction()
    {
        $filename = 'data' . DIRECTORY_SEPARATOR . 'csv' . DIRECTORY_SEPARATOR . 'Foo.csv';;
        $this->file = new SplFileObject($filename);
        $this->file->setFlags(SplFileObject::READ_CSV | SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY | SplFileObject::DROP_NEW_LINE);
    
        $this->file->setCsvControl(',', '""', '\\');
        $this->useFirstRecordAsHeader = true;
    
        $response = $this->getResponse();
        $headers  = $response->getHeaders();
        $headers->addHeaderLine('Content-Type', 'text/csv');
    
        $contents = $this->file->fread($this->file->getSize());
    
        $response->setContent($contents);
        return $response;
    }