PHPackages                             raise-studio/import - 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. raise-studio/import

ActiveFilament-plugin

raise-studio/import
===================

Raise Import — Import for Filament. The simplest and most complete CSV/Excel import plugin. Supports Filament 4 &amp; 5.

v1.0.9-beta.1(1mo ago)017MITPHPPHP ^8.2CI passing

Since Jul 14Pushed 1mo agoCompare

[ Source](https://github.com/raise-studio/import)[ Packagist](https://packagist.org/packages/raise-studio/import)[ RSS](/packages/raise-studio-import/feed)WikiDiscussions master Synced 2w ago

READMEChangelog (1)Dependencies (13)Versions (3)Used By (0)

Raise Import — Import for Filament
==================================

[](#raise-import--import-for-filament)

> 中文文档: [README.zh-CN.md](README.zh-CN.md)

> Raise Import — Import for Filament: the simplest and most complete CSV/Excel import plugin.

**It solves** the pain of adding production-ready CSV/XLSX/ODS import to a Filament admin panel — upload, automatic column mapping, row-level validation, duplicate handling, and a preview wizard — without you hand-building any of that plumbing. **Hand-writing the equivalent** means wiring up a Livewire upload component, OpenSpout parsing, fuzzy header matching, Laravel validation, batch-insert transactions, and error reporting — typically 200+ lines scattered across several files. **With Raise Import it's one line** (`ImportAction::make()->model(User::class)`), turning roughly a half-day of scaffolding into a minute of configuration.

[![Latest Version](https://camo.githubusercontent.com/248f562e3650bf85cb693d66a4f1dea3cae799037be764c15812b0835d1ae60a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f72616973652d73747564696f2f696d706f72742e737667)](https://packagist.org/packages/raise-studio/import)[![Total Downloads](https://camo.githubusercontent.com/be1e091d111396d5ad279f94eddb10f04b88a8ba441dc46ef7f7c766447dab99/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f72616973652d73747564696f2f696d706f72742e737667)](https://packagist.org/packages/raise-studio/import)[![License](https://camo.githubusercontent.com/b37e5ecf509b5c695b37d7384eb95c6ca8229a0b93caad0acdd9b81a96d75a2f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f72616973652d73747564696f2f696d706f72742e737667)](https://github.com/RaiseStudio/import/blob/main/LICENSE)

Features
--------

[](#features)

### Community (Free)

[](#community-free)

FeatureDescription✅CSV / XLSX / ODS importOpenSpout-powered, memory-efficient row-by-row reading✅Auto field detectionAutomatically reads fields from your Eloquent model✅Field configuration API`Field::make()->label()->rules()->default()->options()`✅Automatic column mappingFuzzy matching (similar\_text ≥70%) with Chinese/English aliases✅Data preview before importTable preview with row validation status✅Row-level validationPowered by Laravel Validator✅Duplicate handling3 strategies: **Skip** / **Update** / **Error**✅3-step wizard UIUpload → Mapping → Preview workflow✅CSV delimiter auto-detectComma, semicolon, tab, pipe✅Template downloadCSV template with column headers + sample data✅Import result reportSuccess/failure/skip counts in notification✅mutateBeforeCreate hookModify data before database insert✅Upload file validationExtension whitelist, 50MB limit, empty file check✅Dark mode supportAll views include `dark:` CSS classes✅Multi-languageEnglish (en) and Simplified Chinese (zh\_CN)✅Filament Plugin`RaiseImportPlugin::make()` one-line registration### Pro (Paid)

[](#pro-paid)

FeatureDescription🔷**Pipeline system**8 built-in pipes + custom Closure pipes🔷TrimStringsPipeAuto-trim whitespace from all string fields🔷LowercasePipeConvert email/username to lowercase🔷BcryptPipeHash password fields🔷DateFormatPipeNormalize date formats🔷DefaultValuePipeFill empty fields with defaults🔷MergeColumnsPipeMerge multiple CSV columns into one field🔷SplitColumnPipeSplit one CSV column into multiple fields🔷ClosurePipeAdapt any Closure as a pipe🔷**Advanced column mapping**Merge, split, ignore, and reorder columns🔷**Import history (logs)**Full CRUD resource with stats🔷**5 REST API endpoints**upload / preview / import / template / errors🔷**Queue support**Auto-queues large imports via ShouldQueue🔷**Import stats widget**4 stat cards: total, imported, failed, skipped🔷**Re-import**Retry failed/partial imports🔷**Error report download**CSV file with row-level error details🔷**Multi-column mapping**Map one CSV column to multiple fields🔷**Ignore column checkbox**Skip unwanted columns during mappingInstallation
------------

[](#installation)

```
composer require raise-studio/import
```

### Import History (Import Log)

[](#import-history-import-log)

To see the **Import Log** menu in your Filament sidebar, register the plugin in your `PanelProvider`:

```
use RaiseStudio\Import\RaiseImportPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->plugin(RaiseImportPlugin::make())
        ;
}
```

You can customize the menu's position, label, and icon:

```
->plugin(
    RaiseImportPlugin::make()
        ->navigationGroup('Admin')                    // 放到「Admin」分组
        ->navigationLabel(__('Import Logs'))          // 自定义菜单名
        ->navigationIcon('heroicon-o-document-arrow-down')  // 自定义图标
)
```

Alternatively, register the resource directly for full control:

```
use RaiseStudio\Import\Pro\Resources\ImportLogResource;

->resources([
    ImportLogResource::class,
])
```

> **Note**: Import Log is a Pro feature. In local development environments it's automatically enabled. In production, you'll need a license key (see Configuration below).

Usage
-----

[](#usage)

### Simplest way — one line:

[](#simplest-way--one-line)

```
use RaiseStudio\Import\Actions\ImportAction;

public static function table(Table $table): Table
{
    return $table
        ->headerActions([
            ImportAction::make()
                ->model(User::class),
        ]);
}
```

### Full configuration:

[](#full-configuration)

```
ImportAction::make('import')
    ->model(User::class)
    ->label('Import Users')
    ->icon('arrow-up-tray')
    ->fields([
        Field::make('name')->label('Name')->required(),
        Field::make('email')->label('Email')->rules('email|unique:users'),
        Field::make('phone')->label('Phone')->rules('numeric'),
    ])
    ->uniqueBy('email')
    ->onDuplicate('skip')
    ->chunkSize(500)
    ->rules([
        'name' => 'required|string|max:100',
        'email' => 'email|max:255',
    ])
    ->mutateBeforeCreate(function (array $row) {
        $row['password'] = bcrypt('default123');
        return $row;
    });
```

Requirements
------------

[](#requirements)

- PHP 8.2+
- Filament 4.x or 5.x
- Livewire 3.x (Filament 4) or 4.x (Filament 5)
- OpenSpout 4.x

Configuration
-------------

[](#configuration)

Publish the config file:

```
php artisan vendor:publish --tag=raise-import-config
```

Translations
------------

[](#translations)

Publish translations:

```
php artisan vendor:publish --tag=raise-import-translations
```

Testing
-------

[](#testing)

```
vendor/bin/phpunit
```

Changelog
---------

[](#changelog)

See [CHANGELOG](CHANGELOG.md) for version history.

Pro License
-----------

[](#pro-license)

To unlock Pro features, set your license key (and the shared server secret) in `.env`:

```
RAISE_IMPORT_LICENSE_KEY=your-license-key-here
RAISE_IMPORT_LICENSE_SECRET=shared-hmac-secret
RAISE_IMPORT_LICENSE_PRODUCT=raise-import
```

- `RAISE_IMPORT_LICENSE_KEY` — your Pro license key.
- `RAISE_IMPORT_LICENSE_SECRET` — HMAC secret shared with `raise-license-server`(must equal the server's `LICENSE_SIGNATURE_KEY`). Without it, the plugin rejects **any** positive verification response, so a forged/relayed license endpoint cannot fake a valid license.
- `RAISE_IMPORT_LICENSE_PRODUCT` — product slug sent to the server during verification. Must match a Product slug on `raise-license-server`.

Get a license at

### Verification request &amp; response contract

[](#verification-request--response-contract)

The plugin `POST`s to `RAISE_IMPORT_LICENSE_VERIFY_URL` with:

```
{
  "license_key": "your-license-key-here",
  "site_url": "https://example.com",
  "product": "raise-import"
}
```

The endpoint must return JSON signed with HMAC-SHA256 over `valid|domain|expires_at|edition` (where `valid` is the literal `true`/`false`):

```
{
  "valid": true,
  "domain": "example.com",
  "expires_at": "2026-12-31",
  "edition": "pro",
  "signature": "HMAC_SHA256('true|example.com|2026-12-31|pro', SECRET)"
}
```

The plugin verifies the signature, enforces that `edition === 'pro'`, and locks the key to the returned `domain` (supports `*.example.com` wildcard for subdomains).

**Local exemption is intentionally narrow.** Only loopback hosts (`localhost`, `127.0.0.1`, `[::1]`, `0.0.0.0`) get Pro features without a key. `*.test` / `*.local` TLDs and private IP ranges (`10.x`, `172.16–31.x`, `192.168.x`) are **no longer** exempt — they must present a valid license, just like production. This tightens the free-Pro surface (see strategy note 2026-07-07: 收敛豁免).

### Distributed gate (defense in depth)

[](#distributed-gate-defense-in-depth)

Each Pro feature execution point (the `ProImportAction` wizard setup/run, the queued `ProcessImportJob`, and the `ImportController`) calls `License::gatePro()`**directly** instead of relying solely on the cached `License::isPro()` result. `gatePro()` never reads the static `isPro()` cache and re-evaluates the license on its own (key validity + signature + domain lock + integrity self-check). This means patching `isPro()` to always return `true` is insufficient to unlock the actual Pro features — every critical file re-checks independently.

### Integrity self-check (tamper deterrent)

[](#integrity-self-check-tamper-deterrent)

In addition to online verification, the plugin verifies that its own Pro gatekeeper files (`License.php`, `ProImportAction.php`, `RaiseImportServiceProvider.php`) have not been patched to force Pro mode. Each file's SHA-256 is compared against an expected value shipped in the config. If a file's hash does not match, Pro features are refused and the installation **silently falls back to Community mode** (with a `warning` log entry) — it never crashes.

This is a deterrent, not a hard lock: PHP source always lives on the client's machine, so a determined attacker can still bypass it. It raises the cost of patching the license gate.

Configure it in `config/raise-import.php` (or `.env`):

```
'integrity_disabled' => env('RAISE_IMPORT_INTEGRITY_DISABLED', false),
'integrity_version'  => '1.0.0',
'integrity_hashes'   => [
    'src/License.php' => '...',
    'src/Pro/Actions/ProImportAction.php' => '...',
    'src/RaiseImportServiceProvider.php' => '...',
],
```

- `RAISE_IMPORT_INTEGRITY_DISABLED=true` — disable the check entirely (for legitimate debugging or when you intentionally patch the source).
- `integrity_version` must match the installed package version. If it does not (e.g. you upgraded without regenerating hashes), the check is **skipped**rather than forcing legitimate users into Community mode.
- Empty `integrity_hashes` → check is **skipped** (graceful default). This is the shipped state, so the feature does nothing until you opt in.

Regenerate the hashes for every release with the included command:

```
php artisan raise-import:integrity:rehash
```

It prints the version and the exact `integrity_version` / `integrity_hashes`block to paste into `config/raise-import.php`.

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE) for more information.

###  Health Score

35

—

LowBetter than 77% of packages

Maintenance91

Actively maintained with recent releases

Popularity6

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity33

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.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

48d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/46275694?v=4)[tianby@shu.edu.cn](/maintainers/Tianby)[@tianby](https://github.com/tianby)

---

Top Contributors

[![raiseinfo](https://avatars.githubusercontent.com/u/22998521?v=4)](https://github.com/raiseinfo "raiseinfo (25 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/raise-studio-import/health.svg)

```
[![Health](https://phpackages.com/badges/raise-studio-import/health.svg)](https://phpackages.com/packages/raise-studio-import)
```

###  Alternatives

[filament/filament

A collection of full-stack components for accelerated Laravel app development.

5135.9M4.7k](/packages/filament-filament)[yajra/laravel-oci8

Oracle DB driver for Laravel via OCI8

8793.4M29](/packages/yajra-laravel-oci8)[psalm/plugin-laravel

Psalm plugin for Laravel

3365.5M359](/packages/psalm-plugin-laravel)[filament/infolists

Easily add beautiful read-only infolists to any Livewire component.

1334.0M84](/packages/filament-infolists)[relaticle/comments

A full-featured commenting system for Filament panels

214.1k](/packages/relaticle-comments)[alizharb/filament-activity-log

A security-first audit control center for Filament v4 and v5 with tenant isolation, risk scoring, integrity checks, retention holds, timelines, and dashboards.

31110.0k4](/packages/alizharb-filament-activity-log)

PHPackages © 2026

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