Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

kiasaty's avatar

Best way to export data in xml and csv format

Hi.

I'm looking for the best way to let users export and download data in xml and csv formats.

I have found maatwebsite package to export excel and csv file formats, but it doesn't provide xml.

what do you guys recommend? why packages don't export xml? is it different?

0 likes
16 replies
Talinon's avatar

I've never used this package, but it seems like it could be as simple as:

If you already have the csv:

$formatter = Formatter::make($csvString, Formatter::CSV);
$xml   = $formatter->toXml();

Or create both from something like an array:

$formatter = Formatter::make($array, Formatter::ARR);
$csv   = $formatter->toCsv();
$xml   = $formatter->toXml();

https://github.com/SoapBox/laravel-formatter

kiasaty's avatar

@TALINON - yeah I found this, and already added to my project.

there are two things:

FIRST: In order to this Package to work correctly, I have to prepare the array like this:

        $array = [
            ['firstname' => 'john', 'lastname' => 'trump'],
            ['firstname' => 'july', 'lastname' => 'william'],
            ['firstname' => 'jack', 'lastname' => 'johnson'],
        ];

I have a collection, and when i convert it to array using this:

$arrayList = $people->pluck('person.lastname', 'firstname')->toArray();

the array is like this:

        array:3 [▼
          "john" => "trump"
          "Ajuly" => "william"
          "jack" => "johnson"
        ]

what function should I use instead of pluck function to get the array correctly? as you see I'm getting the last name using relationships.

SECOND: when I solve the first problem, what laravel functions should use to save the output in a file and force the browser to download it without closing the page which the user is on?

Thanks,

Talinon's avatar

The easiest way to prepare your array would be to only get the specific columns you want at the time of the query:

$users = User::get(['firstname', 'lastname'])->toArray();

As for forcing a download of the generated file, I think this would work:

return Response::download($xmlFile, 'export.xml', ['Content-Type: text/xml']);
Poxucis's avatar

@KIASATY - You could use

->map(function ($value, $key) { return ['firstname' => $key, 'lastname' => $value]; });

after pluck() and about downloading

return response()->download($formatter->toCsv());

i think it should do it.

Talinon's avatar

Another way of going about it from an existing collection:

$preparedArray =  $users->map->only(['firstname', 'lastname'])->toArray();
kiasaty's avatar

@TALINON - I'm using relationships. last name is retrieved from another table. so it should be like this:

    $users = User::get(['firstname', 'user.lastname'])->toArray();

but user.lastname retrieves null ;/ I think get function does not support relationships!? /:

kiasaty's avatar

@TALINON - this retrieves this:

    array:7 [▼
      3 => array:2 [▶]
      0 => array:2 [▶]
      6 => array:2 [▶]
      5 => array:2 [▶]
      2 => array:2 [▶]
      1 => array:2 [▶]
      4 => array:2 [▶]
    ]

look at the indexes. it shouldn't be associated array in order to the package work currectly. another problem is that in the array user.lastname is null. problem with relationship.

but this is exactly the structure that is needed. only if 2 problems that i mentioned are solved...

kiasaty's avatar

@POXUCIS - look at the output array:

        array:4 [▼
          "lastname1" => array:2 [▶]
          "lastname2" => array:2 [▶]
          "lastname3" => array:2 [▶]
          "lastname4" => array:2 [▶]
        ]

both first name and last name are retrieved in the child array. but in dont want the parent array to be associated array. as you see last name is mentioned as key. it should be like this:

        array:4 [▼
          0 => array:2 [▶]
          1 => array:2 [▶]
          2 => array:2 [▶]
          3 => array:2 [▶]
        ]
Talinon's avatar

For your first problem, you have another table for user other than the User model? I'm confused on what is going on there, but at any rate, you can fix that with a join (or just use the map() collection method above on whatever collection you're dealing with.

For the join:

$users = User::join('other_table', 'users.id', '=', 'other_table.id')->get(['firstname', 'other_table.lastname']);

As for the associative array, you can use keyBy()

$users->keyBy('whatever_key')->toArray();

Talinon's avatar

Sorry - I just read your previous post again.. you're saying there shouldn't be an associative array. You can use ->values()

kiasaty's avatar

@TALINON - why

        return response()->download($filePath)->deleteFileAfterSend();

works, but

        return Storage::download($filePath);

throws this exception: "File not found at path: E:/Project/storage/app/public/report.csv"

Talinon's avatar

Have you sym-linked your storage? php artisan storage:link

Make sure you're using the right disk as well.

    return Storage::disk('local')->download($filePath); // for example

and also check your settings within config/filesystems.php

kiasaty's avatar

@TALINON - Thanks a lot, I'm gonna test them. I should go deeply through the document to fully understand the logic.

firstname and lastname are examples. I guess there are not good examples obviously. my data is different. there are two models, and "lastname" example is a foreign key in the first model.

jmvdholst's avatar

I tried to install the soapbox/laravel-formatter package in LAravel 6.9, but that gave a bunch of errors as this package hasn't been updated to use in Laravel 6.9

Please or to participate in this conversation.