Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP - Export to CSV an array of objects

I want to export an array of objects in CSV :

array(10) {
  [0]=>
  object(Produit)#228 (36) {
    ["id_produit":protected]=> string(4) "9999"
    ["reference":protected]=> string(9) "reference1"
}
  [1]=>
  object(Produit)#228 (36) {
    ["id_produit":protected]=> string(4) "8888"
    ["reference":protected]=> string(9) "reference2"
}
}

IN something like :

id_produit | reference | ...
9999 | reference1 | ...
8888 | reference2 | ...

The first row : list of attribut / column

The other row : value of the attribut of the Object

True Example of array with object : http://pastebin.com/8Eyf46pb

I tried this : Convert array into csv but it doesn't work for me.

Is it possible to do this (and how ?) or I have to write each attribute in a loop ?

like image 688
Snow Avatar asked Feb 10 '14 17:02

Snow


People also ask

How do I convert an array to a CSV file?

To convert an array into a CSV file we can use fputcsv() function. The fputcsv() function is used to format a line as CSV (comma separated values) file and writes it to an open file.

Can CSV contain arrays?

Can CSV contain array? Importing CSVs does not handle complex types like arrays, it is designed to import simple, flat data. The only types that are currently supported are strings and numbers.

How does PHP Fputcsv work?

fputcsv() formats a line (passed as a fields array) as CSV and writes it (terminated by a newline) to the specified file stream .

What is Fgetcsv function in PHP?

The fgetcsv() function parses a line from an open file, checking for CSV fields.


2 Answers

It would be pretty easy if all your properties are public:

// Test class
class Produit
{
    public $id_produit;
    public $reference;

    // Test data
    public function  __construct()
    {
        $this->id_produit = rand(1, 255);
        $this->reference = rand(1, 255);
    }
}

// Test data array
$array = array(new Produit(), new Produit());

// Notice, you can only use a single character as a delimiter
$delimiter = '|';

if (count($array) > 0) {
    // prepare the file
    $fp = fopen('test/file.csv', 'w');

    // Save header
    $header = array_keys((array)$array[0]);
    fputcsv($fp, $header, $delimiter);

    // Save data
    foreach ($array as $element) {
        fputcsv($fp, (array)$element, $delimiter);
    }
}

But as I can see, your properties are protected. Which means we can't access properties outside the object as well as loop through them or use (array) typecasting. So in this case you must make some changes ot the object:

// Test class
class Produit
{
    // ...

    public function getProperties()
    {
        return array('id_produit', 'reference');
    }

    public function toArray()
    {
        $result = array();

        foreach ($this->getProperties() as $property) {
            $result[$property] = $this->$property;
        }

        return $result;
    }
}

And then instead of typecasting you can use new method toArray like this:

// Save data
foreach ($array as $element) {
    fputcsv($fp, $element->toArray(), $delimiter);
}

Also thanks to new mehod getProperties we can change header getting:

// Save header
fputcsv($fp, $array[0]->getProperties(), $delimiter);
like image 110
Hast Avatar answered Oct 13 '22 22:10

Hast


I've now tested the below code and it does seem to work. Reflection was the answer.

I tried to get it working on phpfiddle hence the php://temp but it didn't work unfortunately

<?php
class Produit
{
    public $id_produit;
    public $reference;

    // Test data
    public function  __construct()
    {
        $this->id_produit = rand(1, 255);
        $this->reference = rand(1, 255);
    }
}

$array = array(new Produit(), new Produit());


$delimiter='|';
$fp=fopen('php://temp', 'w'); //replace this bit with a file name
$header=false;
foreach($array as $Produit){
    $Reflection = new ReflectionClass($Produit);
    $properties = $Reflection->getProperties();
    $row=array();
    foreach($properties as $prop){
        $row[$prop->getName()] = $prop->getValue($Produit);
    }
    if(!$header){
        fputcsv($fp, array_keys($row), $delimiter);
        $header=true;
    }
    fputcsv($fp, $row, $delimiter);
}

//now show what has been written, you will want to remove this section
fseek($fp, 0);
fpassthru($fp);
//ends

fclose($fp);
like image 28
edmondscommerce Avatar answered Oct 13 '22 20:10

edmondscommerce