Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Exporter Laravel Package

mathieutu/exporter

A Laravel package for exporting data to CSV/Excel with a simple, fluent API. Define exportable columns, handle relations and formatting, and generate downloadable files effortlessly.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package via Composer and, if you plan to customize defaults, publish the config:

composer require mathieutu/exporter
php artisan vendor:publish --provider="MathieuTu\Exporter\ExporterServiceProvider"

There are two entry points; open the README for the exact signatures, then pick one:

  1. The Exportable trait — add it to an Eloquent model and declare a default export map:
use MathieuTu\Exporter\Exportable;

class User extends Model
{
    use Exportable;

    protected $export = ['id', 'name', 'email'];
}

$user->export();                   // uses $export
$user->export(['name', 'email']);  // ad-hoc override
  1. The Exporter facade — for objects/arrays that aren't Eloquent models:
use MathieuTu\Exporter\Exporter;

Exporter::export($user, ['id', 'name']);
Exporter::export(['first' => 'Ada', 'last' => 'Lovelace'], ['first']);

Your first real use case is almost always replacing a hand-rolled ->map(fn ($m) => ['id' => ..., 'name' => ...]) in a controller or API resource. Start by exporting one model in php artisan tinker to confirm the attribute resolution (plain column vs. accessor vs. relation) matches your expectation before wiring it into a resource class.

Implementation Patterns

Default map on the model, overrides at the edge. Put the canonical shape in $export so every consumer gets the same baseline, and only override in controllers/resources where a screen needs less or more. This keeps the "what is a User publicly" decision in one file instead of scattered across transformers.

Shape JSON responses. The package returns plain arrays/scalars, so it slots directly into response()->json() or an ApiResource::toArray() without a transformer library:

public function index()
{
    return User::paginate()->through(fn (User $u) => $u->export(['id', 'name', 'avatar']));
}

->through() (or ->map() on older Laravel) is the cleanest way to apply the same export to a paginator/collection.

Different exports for different audiences. Define a couple of named maps (e.g. $export, $exportAdmin) as arrays or small methods on the model, then pass them explicitly — the package is just a resolver, so nothing stops you from having publicExport() / adminExport() helpers that call export([...]).

Nested attributes. Use dot notation for relations and accessors ('posts.title', 'profile.city') — this is the main reason to prefer the package over pluck/only. Combine with with()/load() on the query so relations are eager-loaded before the export runs.

Arrays and DTOs. Because it works on arrays too, you can export plain config arrays, request payloads, or lightweight DTOs without touching Eloquent. This is handy in Artisan commands, imports/exports, and tests where you want the same shaping logic applied to fixtures.

Wrap it in a Resource or a service. Rather than calling export() in a dozen controllers, expose UserResource::make($user) that internally does $user->export($this->map). That gives you one place to change the contract and keeps the package as an implementation detail.

Gotchas and Tips

It does not (generally) honour $hidden, $visible, or $appends. The exporter resolves exactly the keys you name. That's the point, but it means you can leak a password hash by adding 'password' to an export map — treat $export with the same scrutiny as a $fillable. Never pass unvalidated user input into the attribute list (e.g. ?fields= query params); always intersect against a whitelist.

Relationships cause N+1s. Dot-notation is convenient and will silently lazy-load. Always ->with('posts') on the query, or eager-load in the repository, before exporting. If you're exporting inside a loop over a collection, check DB::listen() / Telescope once — this is the most common performance regression with exporter-style packages.

Missing keys are forgiving by design. A typo in an attribute name usually yields a null (or a skipped entry) rather than a loud exception. During development, dump the raw output:

dump($user->export(['id', 'name', 'emial']));

and compare against $user->getAttributes() / $user->toArray(). If a key is missing but you expected an accessor, confirm it's a real accessor (getFooAttribute) and not just a method — the resolver has rules about what counts as an exportable attribute, and it differs between models and plain arrays.

Eloquent vs. plain arrays behave differently. On models you get casts, accessors, and relations; on arrays you only get keys that exist (nested arrays need dot paths to match too). If you build a code path that handles both, test both — array exports won't invent attributes.

Config quirks. The published config is small but controls the default property name and fallback behaviour. If ->export() returns what looks like an empty/stale map, check whether the trait is reading $export or a config-driven key. Clear the config cache after edits: php artisan config:clear.

Version/compat risk. This is a low-star, single-maintainer package. Pin it in composer.json, and keep your own thin wrapper (UserResource) between your app and the package so swapping it for a few lines of array_map or Arr::only later is a one-file change. There is no large community to lean on for edge cases.

Extension points. Prefer composing the package (custom export maps, wrapper classes, per-model helper methods) over forking. If you need behaviour the resolver doesn't provide — conditional keys, value transformation, typed output — do it after the export call (array_map over the result, or a tap-style helper), which keeps the dependency at arm's length.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager