PHPackages                             toporia/tabula - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [File &amp; Storage](/categories/file-storage)
4. /
5. toporia/tabula

ActiveLibrary[File &amp; Storage](/categories/file-storage)

toporia/tabula
==============

High-performance Excel/CSV import &amp; export for Toporia Framework - handles millions of rows

00PHP

Since Dec 21Pushed 4mo agoCompare

[ Source](https://github.com/Minhphung7820/toporia-tabula)[ Packagist](https://packagist.org/packages/toporia/tabula)[ RSS](/packages/toporia-tabula/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

Toporia Tabula
==============

[](#toporia-tabula)

High-performance Excel/CSV import &amp; export for Toporia Framework. Handles millions of rows with O(1) memory usage.

Features
--------

[](#features)

- **Streaming I/O**: O(1) memory - process millions of rows without memory issues
- **Chunk Processing**: Configurable batch sizes for optimal performance
- **Queue Support**: Background processing for large files
- **Validation**: Built-in row validation with custom rules
- **Multiple Formats**: XLSX, CSV, ODS support
- **Multiple Sheets**: Export to multiple sheets in one file
- **Progress Tracking**: Monitor import/export progress
- **Event System**: Hook into lifecycle events
- **Clean Architecture**: Interface-based design, SOLID principles

Installation
------------

[](#installation)

```
composer require toporia/tabula
```

Quick Start
-----------

[](#quick-start)

### Import

[](#import)

```
use Toporia\Tabula\Tabula;
use Toporia\Tabula\Imports\BaseImport;
use Toporia\Tabula\Contracts\WithChunkReadingInterface;
use Toporia\Tabula\Contracts\WithHeadingRowInterface;

class UsersImport extends BaseImport implements WithChunkReadingInterface, WithHeadingRowInterface
{
    public function row(array $row, int $rowNumber): void
    {
        User::create([
            'name' => $row['name'],
            'email' => $row['email'],
        ]);
    }

    public function chunkSize(): int
    {
        return 1000;
    }

    public function headingRow(): int
    {
        return 1;
    }
}

// Run import
$result = Tabula::import(new UsersImport(), '/path/to/users.xlsx');

echo "Imported: {$result->getSuccessRows()} rows";
echo "Failed: {$result->getFailedRows()} rows";
echo "Duration: {$result->getDuration()} seconds";
```

### Export

[](#export)

```
use Toporia\Tabula\Tabula;
use Toporia\Tabula\Exports\BaseExport;

class UsersExport extends BaseExport
{
    public function data(): iterable
    {
        // Use generator for large datasets
        foreach (User::query()->cursor() as $user) {
            yield [
                'name' => $user->name,
                'email' => $user->email,
                'created_at' => $user->created_at,
            ];
        }
    }

    public function headers(): array
    {
        return ['Name', 'Email', 'Created At'];
    }
}

// Export to file
$result = Tabula::export(new UsersExport(), '/path/to/users.xlsx');

// Or download directly
Tabula::download(new UsersExport(), 'users.xlsx');
```

### Queue Large Files

[](#queue-large-files)

```
// Queue import for background processing
Tabula::queueImport(UsersImport::class, '/path/to/large-file.xlsx');

// Queue export
Tabula::queueExport(UsersExport::class, '/path/to/output.xlsx');
```

Advanced Usage
--------------

[](#advanced-usage)

### Validation

[](#validation)

```
use Toporia\Tabula\Contracts\WithValidationInterface;

class UsersImport extends BaseImport implements WithValidationInterface
{
    public function row(array $row, int $rowNumber): void
    {
        User::create($row);
    }

    public function rules(): array
    {
        return [
            'email' => 'required|email',
            'name' => 'required|min_length:2',
        ];
    }

    public function customValidationMessages(): array
    {
        return [
            'email.required' => 'Email is required',
            'email.email' => 'Invalid email format',
        ];
    }
}
```

### Row Mapping

[](#row-mapping)

```
use Toporia\Tabula\Contracts\WithMappingInterface;

class UsersImport extends BaseImport implements WithMappingInterface
{
    public function row(array $row, int $rowNumber): void
    {
        User::create($row);
    }

    public function map(array $row): array
    {
        return [
            'name' => $row['Full Name'] ?? $row[0],
            'email' => strtolower($row['Email Address'] ?? $row[1]),
            'age' => (int) ($row['Age'] ?? $row[2]),
        ];
    }
}
```

### Multiple Sheets Export

[](#multiple-sheets-export)

```
use Toporia\Tabula\Contracts\WithMultipleSheetsInterface;
use Toporia\Tabula\Contracts\WithTitleInterface;

class ReportExport extends BaseExport implements WithMultipleSheetsInterface
{
    public function sheets(): array
    {
        return [
            new UsersSheet(),
            new OrdersSheet(),
            new ProductsSheet(),
        ];
    }

    public function data(): iterable
    {
        return [];
    }

    public function headers(): array
    {
        return [];
    }
}

class UsersSheet extends BaseExport implements WithTitleInterface
{
    public function title(): string
    {
        return 'Users';
    }

    public function data(): iterable
    {
        return User::all();
    }

    public function headers(): array
    {
        return ['ID', 'Name', 'Email'];
    }
}
```

### Progress Tracking

[](#progress-tracking)

```
use Toporia\Tabula\Contracts\WithProgressInterface;

class UsersImport extends BaseImport implements WithProgressInterface
{
    public function row(array $row, int $rowNumber): void
    {
        User::create($row);
    }

    public function onProgress(int $current, int $total, float $percentage): void
    {
        echo "Progress: {$percentage}% ({$current}/{$total})\n";
    }
}
```

### Events

[](#events)

```
use Toporia\Tabula\Contracts\WithEventsInterface;

class UsersImport extends BaseImport implements WithEventsInterface
{
    public function row(array $row, int $rowNumber): void
    {
        User::create($row);
    }

    public function registerEvents(): array
    {
        return [
            'beforeImport' => fn() => Log::info('Starting import'),
            'afterImport' => fn($result) => Log::info("Imported {$result->getTotalRows()} rows"),
            'beforeChunk' => fn($index) => Log::info("Processing chunk {$index}"),
            'afterChunk' => fn($index, $count) => Log::info("Processed {$count} rows"),
            'onError' => fn($e, $row, $rowNum) => Log::error("Error on row {$rowNum}"),
        ];
    }
}
```

### Model Traits

[](#model-traits)

```
use Toporia\Tabula\Concerns\Importable;
use Toporia\Tabula\Concerns\Exportable;

class User extends Model
{
    use Importable, Exportable;
}

// Import with mapping
User::importFrom('/path/to/users.xlsx', function ($row) {
    return [
        'name' => $row['name'],
        'email' => $row['email'],
    ];
});

// Export specific columns
User::exportTo('/path/to/users.xlsx', ['id', 'name', 'email']);

// Download
User::downloadAs('users.xlsx', ['id', 'name', 'email']);
```

### Quick Exports (Fluent API)

[](#quick-exports-fluent-api)

```
use Toporia\Tabula\Exports\FromQueryExport;
use Toporia\Tabula\Exports\FromCollectionExport;

// Export from query with O(1) memory
$export = FromQueryExport::make(User::query()->where('active', true))
    ->columns(['id', 'name', 'email', 'created_at'])
    ->withHeaders(['ID', 'Name', 'Email', 'Created At'])
    ->format('created_at', fn($v) => $v?->format('Y-m-d'));

Tabula::export($export, '/path/to/users.xlsx');

// Export from collection/array
$export = FromCollectionExport::make($users)
    ->columns(['name', 'email'])
    ->withHeaders(['Name', 'Email']);

Tabula::export($export, '/path/to/users.xlsx');
```

### Quick Model Imports (Fluent API)

[](#quick-model-imports-fluent-api)

```
use Toporia\Tabula\Imports\ToModelImport;

// Import directly to model with upsert
$import = ToModelImport::make(User::class)
    ->map(fn($row) => [
        'name' => $row['name'],
        'email' => $row['email'],
    ])
    ->upsertBy(['email'])  // Update if email exists
    ->chunk(1000)
    ->batch(500);

Tabula::import($import, '/path/to/users.xlsx');
```

### Console Commands

[](#console-commands)

```
# Import from command line
php console tabula:import "App\Imports\UsersImport" /path/to/file.xlsx --chunk=5000

# Export from command line
php console tabula:export "App\Exports\UsersExport" /path/to/output.xlsx
```

Performance
-----------

[](#performance)

Tested with files containing millions of rows:

OperationRowsMemoryTimeImport1,000,000~50MB~120sExport1,000,000~30MB~90sCSV Import1,000,000~20MB~45sCSV Export1,000,000~15MB~30sLicense
-------

[](#license)

MIT

###  Health Score

17

—

LowBetter than 6% of packages

Maintenance50

Moderate activity, may be stable

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity12

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/1cc240e87c451f2dd614b87bb0d07039e4a20d8b391221c651172cf341e0b6cd?d=identicon)[Minhphung7820](/maintainers/Minhphung7820)

---

Top Contributors

[![Minhphung7820](https://avatars.githubusercontent.com/u/110077842?v=4)](https://github.com/Minhphung7820 "Minhphung7820 (11 commits)")

### Embed Badge

![Health badge](/badges/toporia-tabula/health.svg)

```
[![Health](https://phpackages.com/badges/toporia-tabula/health.svg)](https://phpackages.com/packages/toporia-tabula)
```

###  Alternatives

[knplabs/gaufrette

PHP library that provides a filesystem abstraction layer

2.5k39.8M123](/packages/knplabs-gaufrette)[superbalist/flysystem-google-storage

Flysystem adapter for Google Cloud Storage

26320.6M30](/packages/superbalist-flysystem-google-storage)[illuminate/filesystem

The Illuminate Filesystem package.

15161.6M2.6k](/packages/illuminate-filesystem)[creocoder/yii2-flysystem

The flysystem extension for the Yii framework

2931.7M62](/packages/creocoder-yii2-flysystem)[flowjs/flow-php-server

PHP library for handling chunk uploads. Works with flow.js html5 file uploads.

2451.6M15](/packages/flowjs-flow-php-server)[madnest/madzipper

Easier zip file handling for Laravel applications.

1382.3M6](/packages/madnest-madzipper)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
