PHP code example of elachagui / laravel-smart-importer
1. Go to this page and download the library: Download elachagui/laravel-smart-importer library . Choose the download type require .
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
elachagui / laravel-smart-importer example snippets
return [
// Models allowed for import (security)
'allowed_models' => [
App\Models\User::class,
App\Models\Product::class,
],
// Default chunk size for processing
'chunk_size' => 1000,
// Default duplicate strategy: 'skip', 'update', 'fail'
'duplicate_strategy' => 'skip',
// Queue configuration
'queue' => [
'enabled' => false,
'connection' => env('QUEUE_CONNECTION', 'sync'),
'queue' => 'imports',
],
// Stop on first validation error
'stop_on_error' => false,
// Wrap import in database transaction
'use_transaction' => false,
// Disable model events during import
'disable_model_events' => false,
// File storage configuration
'storage' => [
'disk' => 'local',
'path' => 'imports',
],
// CSV settings
'csv' => [
'delimiter' => ',',
'enclosure' => '"',
'escape' => '\\',
'encoding' => 'UTF-8',
],
// Logging
'logging' => [
'enabled' => true,
'channel' => env('LOG_CHANNEL', 'stack'),
],
];
use Elachagui\SmartImporter\Facades\SmartImporter;
$import = SmartImporter::make()
->model(App\Models\User::class)
->file($request->file('file'))
->mapping([
'Full Name' => 'name',
'Email Address' => 'email',
'Phone Number' => 'phone',
])
->import();
$import = SmartImporter::make()
->model(App\Models\User::class)
->file($request->file('file'))
->mapping([
'Name' => 'name',
'Email' => 'email',
])
->duplicateStrategy('update') // or 'skip', 'fail'
->import();
// Or use convenience methods
->skipDuplicates()
->updateDuplicates()
->failOnDuplicates()
use Carbon\Carbon;
$import = SmartImporter::make()
->model(App\Models\Product::class)
->file($request->file('file'))
->mapping([
'Product Name' => 'name',
'Price' => 'price',
'Created Date' => 'created_at',
])
->transform([
'price' => fn($value) => floatval(str_replace(['$', ','], '', $value)),
'created_at' => fn($value) => Carbon::parse($value),
])
->import();
$import = SmartImporter::make()
->model(App\Models\User::class)
->file($request->file('file'))
->mapping([
'Name' => 'name',
'Email' => 'email',
])
->queue() // Use default queue
// or
->queue('redis', 'high-priority') // Custom connection and queue
->import();
$import = SmartImporter::make()
->model(App\Models\User::class)
->file($request->file('file'))
->mapping([
'Name' => 'name',
'Email' => 'email',
])
->chunkSize(500)
->uniqueBy(['email'])
->stopOnError()
->withTransaction()
->withoutModelEvents()
->import();
$preview = SmartImporter::make()
->file($request->file('file'))
->preview(10);
// Returns:
// [
// 'headers' => ['Name', 'Email', 'Phone'],
// 'rows' => [...],
// 'total_rows' => 100,
// ]
$headers = SmartImporter::make()
->file($request->file('file'))
->getHeaders();
// Returns: ['Name', 'Email', 'Phone']
use App\Models\Product;
use App\Models\Category;
$import = SmartImporter::make()
->model(Product::class)
->file($file)
->mapping([
'SKU' => 'sku',
'Name' => 'name',
'Price' => 'price',
])
->relations([
'category' => [
'type' => 'belongsTo',
'model' => Category::class,
'file_column' => 'Category Name', // Column in CSV/Excel
'lookup_by' => 'name', // Column to search in categories table
'create_if_missing' => true, // Create category if not found
'create_mapping' => [ // Optional: map additional fields when creating
'Category Name' => 'name',
'Category Slug' => 'slug',
],
'defaults' => [ // Optional: default values when creating
'active' => true,
],
'foreign_key' => 'category_id', // Optional: explicit foreign key (auto-detected)
'owner_key' => 'id', // Optional: parent's key column (default: 'id')
],
])
->import();
->relations([
'warehouse' => [
'type' => 'belongsTo',
'model' => Warehouse::class,
'file_columns' => ['Region Code', 'Warehouse Code'],
'lookup_columns' => ['region_code', 'code'],
],
])
use App\Models\Order;
use App\Models\OrderItem;
$import = SmartImporter::make()
->model(Order::class)
->file($file)
->mapping([
'Order Number' => 'order_number',
'Total' => 'total',
])
->relations([
// HasMany with column mapping
'items' => [
'type' => 'hasMany',
'model' => OrderItem::class,
'foreign_key' => 'order_id',
'mapping' => [
'Item Name' => 'product_name',
'Quantity' => 'quantity',
'Unit Price' => 'price',
],
],
])
->import();
->relations([
'variants' => [
'type' => 'hasMany',
'model' => ProductVariant::class,
'foreign_key' => 'product_id',
'file_column' => 'Sizes', // e.g., "S,M,L,XL"
'separator' => ',',
'mapping' => ['Sizes' => 'size'],
'defaults' => ['stock' => 0],
],
])
->relations([
'items' => [
'type' => 'hasMany',
'model' => OrderItem::class,
'foreign_key' => 'order_id',
'file_column' => 'Items JSON',
// File contains: [{"name":"Widget","qty":2},{"name":"Gadget","qty":1}]
],
])
use App\Models\Product;
use App\Models\Tag;
$import = SmartImporter::make()
->model(Product::class)
->file($file)
->mapping([
'SKU' => 'sku',
'Name' => 'name',
])
->relations([
'tags' => [
'type' => 'belongsToMany',
'model' => Tag::class,
'file_column' => 'Tags', // e.g., "electronics,featured,sale"
'lookup_by' => 'name', // Find tags by name
'separator' => ',', // How values are separated
'create_if_missing' => true, // Create tags that don't exist
'sync_mode' => 'sync', // 'sync', 'attach', 'toggle', 'syncWithoutDetaching'
'pivot_data' => [ // Optional: data for pivot table
'assigned_by' => 'import',
],
'pivot_columns' => [ // Optional: map file columns to pivot columns
'Tag Priority' => 'priority',
],
],
])
->import();
use App\Models\Product;
use App\Models\Comment;
$import = SmartImporter::make()
->model(Product::class)
->file($file)
->mapping([
'SKU' => 'sku',
'Name' => 'name',
])
->relations([
'comments' => [
'type' => 'morphMany',
'model' => Comment::class,
'mapping' => [
'Review' => 'body',
'Rating' => 'rating',
],
],
])
->import();
use App\Models\Comment;
use App\Models\Product;
$import = SmartImporter::make()
->model(Comment::class)
->file($file)
->mapping([
'Body' => 'body',
])
->relations([
'commentable' => [
'type' => 'morphTo',
'model' => Product::class,
'file_column' => 'Product SKU',
'lookup_by' => 'sku',
'morph_name' => 'commentable', // Optional: morph name
'create_if_missing' => true,
],
])
->import();
->relations([
'tags' => [
'type' => 'morphToMany',
'model' => Tag::class,
'file_column' => 'Tags',
'lookup_by' => 'name',
'separator' => ',',
'create_if_missing' => true,
],
])
use App\Models\Country;
use App\Models\User;
use App\Models\Post;
$import = SmartImporter::make()
->model(Country::class)
->file($file)
->mapping([
'Country Name' => 'name',
])
->relations([
'posts' => [
'type' => 'hasManyThrough',
'model' => Post::class,
'through_model' => User::class,
'first_key' => 'country_id', // Foreign key on User
'second_key' => 'user_id', // Foreign key on Post
'through_mapping' => [ // Create the intermediate User
'Author Name' => 'name',
'Author Email' => 'email',
],
'mapping' => [ // Create the Post
'Post Title' => 'title',
'Post Body' => 'body',
],
],
])
->import();
use Elachagui\SmartImporter\Contracts\Importable;
use Illuminate\Database\Eloquent\Model;
class Product extends Model implements Importable
{
public static function importRules(): array
{
return [
'sku' => 'rtRelations(): array
{
return [
'category' => [
'type' => 'belongsTo',
'model' => Category::class,
'file_column' => 'category_name',
'lookup_by' => 'name',
'create_if_missing' => true,
],
'tags' => [
'type' => 'belongsToMany',
'model' => Tag::class,
'file_column' => 'tags',
'lookup_by' => 'name',
'separator' => ',',
'create_if_missing' => true,
],
];
}
}
$import = SmartImporter::make()
->model(Product::class)
->file($file)
->mapping([
'SKU' => 'sku',
'Name' => 'name',
'Price' => 'price',
])
->import(); // Relations are auto-loaded from model
$import = SmartImporter::make()
->model(Order::class)
->file($file)
->mapping([
'Order Number' => 'order_number',
'Total' => 'total',
])
->relations([
// BelongsTo: Set customer_id
'customer' => [
'type' => 'belongsTo',
'model' => Customer::class,
'file_column' => 'Customer Email',
'lookup_by' => 'email',
'create_if_missing' => true,
'create_mapping' => [
'Customer Email' => 'email',
'Customer Name' => 'name',
],
],
// HasMany: Create order items
'items' => [
'type' => 'hasMany',
'model' => OrderItem::class,
'foreign_key' => 'order_id',
'mapping' => [
'Product' => 'product_name',
'Qty' => 'quantity',
'Price' => 'price',
],
],
// BelongsToMany: Sync tags
'tags' => [
'type' => 'belongsToMany',
'model' => Tag::class,
'file_column' => 'Tags',
'lookup_by' => 'name',
'separator' => ',',
'create_if_missing' => true,
],
// MorphMany: Add comments
'comments' => [
'type' => 'morphMany',
'model' => Comment::class,
'mapping' => [
'Note' => 'body',
],
],
])
->import();
use Elachagui\SmartImporter\Contracts\Importable;
use Illuminate\Database\Eloquent\Model;
class User extends Model implements Importable
{
public static function importRules(): array
{
return [
'name' => ' Define relations for import
public static function importRelations(): array
{
return [
// ... relation definitions
];
}
}
use Elachagui\SmartImporter\Models\Import;
$import = Import::find($id);
// Access import data
$import->model; // Target model class
$import->file_path; // Path to imported file
$import->total_rows; // Total rows in file
$import->processed_rows; // Rows processed
$import->success_rows; // Successfully imported
$import->failed_rows; // Failed rows
$import->skipped_rows; // Skipped (duplicates)
$import->status; // pending, processing, completed, failed, cancelled
$import->mapping; // Column mapping (array)
$import->started_at; // When import started
$import->finished_at; // When import finished
// Check status
$import->isPending();
$import->isProcessing();
$import->isCompleted();
$import->isFailed();
$import->isCancelled();
// Get progress
$import->getProgressPercentage(); // Returns 0-100
// Get errors
$import->errors; // HasMany relationship to ImportError
$import = SmartImporter::find($id);
SmartImporter::cancel($import);
use Elachagui\SmartImporter\Events\ImportStarted;
use Elachagui\SmartImporter\Events\ImportCompleted;
use Elachagui\SmartImporter\Events\ImportFailed;
use Elachagui\SmartImporter\Events\RowImported;
// In your EventServiceProvider
protected $listen = [
ImportStarted::class => [
SendImportStartedNotification::class,
],
ImportCompleted::class => [
SendImportCompletedNotification::class,
],
ImportFailed::class => [
SendImportFailedNotification::class,
],
RowImported::class => [
ProcessImportedRow::class,
],
];
// ImportStarted
public Import $import;
// ImportCompleted
public Import $import;
public function getSummary(): array; // Returns summary data
// ImportFailed
public Import $import;
public Throwable $exception;
public function getErrorMessage(): string;
public function getErrorDetails(): array;
// RowImported
public Import $import;
public int $rowNumber;
public array $data;
public string $action; // 'created' or 'updated'
public function wasCreated(): bool;
public function wasUpdated(): bool;
use Elachagui\SmartImporter\Exceptions\ImportException;
try {
$import = SmartImporter::make()
->model(App\Models\User::class)
->file($file)
->mapping($mapping)
->import();
} catch (ImportException $e) {
// Handle import-specific errors
$message = $e->getMessage();
$rowNumber = $e->getRowNumber();
$rowData = $e->getRowData();
$context = $e->getContext();
}
namespace App\Http\Controllers;
use App\Models\Product;
use App\Models\Category;
use App\Models\Tag;
use Elachagui\SmartImporter\Facades\SmartImporter;
use Elachagui\SmartImporter\Exceptions\ImportException;
use Illuminate\Http\Request;
class ProductImportController extends Controller
{
public function preview(Request $request)
{
$request->validate([
'file' => ' ->model(Product::class)
->file($request->file('file'))
->mapping([
'SKU' => 'sku',
'Product Name' => 'name',
'Price' => 'price',
])
->relations([
'category' => [
'type' => 'belongsTo',
'model' => Category::class,
'file_column' => 'Category',
'lookup_by' => 'name',
'create_if_missing' => true,
],
'tags' => [
'type' => 'belongsToMany',
'model' => Tag::class,
'file_column' => 'Tags',
'lookup_by' => 'name',
'separator' => ',',
'create_if_missing' => true,
],
])
->transform([
'price' => fn($v) => floatval(str_replace(['$', ','], '', $v)),
])
->updateDuplicates()
->queue()
->import();
return response()->json([
'message' => 'Import queued successfully',
'import_id' => $import->id,
]);
} catch (ImportException $e) {
return response()->json([
'message' => $e->getMessage(),
], 422);
}
}
public function status(int $id)
{
$import = SmartImporter::findWithErrors($id);
if (!$import) {
return response()->json(['message' => 'Import not found'], 404);
}
return response()->json([
'status' => $import->status,
'progress' => $import->getProgressPercentage(),
'total_rows' => $import->total_rows,
'processed_rows' => $import->processed_rows,
'success_rows' => $import->success_rows,
'failed_rows' => $import->failed_rows,
'skipped_rows' => $import->skipped_rows,
'errors' => $import->errors->map(fn($e) => [
'row' => $e->row_number,
'errors' => $e->errors,
]),
]);
}
public function cancel(int $id)
{
$import = SmartImporter::find($id);
if (!$import) {
return response()->json(['message' => 'Import not found'], 404);
}
$cancelled = SmartImporter::cancel($import);
return response()->json([
'cancelled' => $cancelled,
]);
}
}
bash
php artisan vendor:publish --tag=smart-importer-config
bash
php artisan migrate