Search code examples
phpcsvsplfileobject

How to assign SplFileObject::fpassthru output to variable


I'm currently writing some data to an SplFileObject like this:

$fileObj = new SplFileObject('php://text/plain,', "w+");

foreach($data as $row) {

    $fileObj->fputcsv($row);
}

Now, I want to dump the whole output (string) to a variable.

I know that SplFileObject::fgets gets the output line by line (which requires a loop) but I want to get it in one go, ideally something like this:

$fileObj->rewind();
$output = $fileObj->fpassthru();

However, this does not work as it simply prints to standard output.

There's a solution for what I'm trying to achieve using stream_get_contents():

pass fpassthru contents to variable

However, that method requires you to have direct access to the file handle.

SplFileObject hides the file handle in a private property and therefore not accessible.

Is there anything else I can try?


Solution

  • After writing, do a rewind() then you can read everything. The example is for understanding:

    $fileObj = new SplFileObject('php://memory', "w+");
        
    $row = [1,2,'test'];  //Test Data
        
    $fileObj->fputcsv($row);
    $fileObj->rewind();
        
    //now Read
    $rowCopy = $fileObj->fgetcsv();
        
    var_dump($row == $rowCopy);//bool(true)
    
    $fileObj->rewind();
    $strLine = $fileObj->fgets();  //read as string
    $expected = "1,2,test\n";
    
    var_dump($strLine === $expected);  //bool(true)
    
    //several lines
    $fileObj->rewind();
    $fileObj->fputcsv(['test2',3,4]);
    $fileObj->fputcsv(['test3',5,6]);
    
    $fileObj->rewind();
    for($content = ""; $row = $fileObj->fgets(); $content .= $row);
    
    var_dump($content === "test2,3,4\ntest3,5,6\n");  //bool(true)
    

    If you absolutely have to fetch your content with only one command then you can do this too

    // :
    $length = $fileObj->ftell(); 
    $fileObj->rewind();
    $content = $fileObj->fread($length);
    

    getSize() doesn't work here.