Weave Code
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

Laravel Model Upload Laravel Package

fromhome/laravel-model-upload

View on GitHub
Deep Wiki
Context7

Getting Started

The laravel-model-upload package simplifies handling Excel file uploads for Laravel Eloquent models by leveraging Laravel Excel. To begin, install the package via Composer and publish its migrations and config:

composer require atfromhome/laravel-model-upload
php artisan vendor:publish --tag="laravel-model-upload-migrations"
php artisan vendor:publish --tag="laravel-model-upload-config"
php artisan migrate

First Use Case: Upload a CSV/Excel file containing user data and import it into a User model. Start by defining a UserUpload class extending ModelUpload (likely provided by the package) and specifying the import rules:

use Atfromhome\LaravelModelUpload\ModelUpload;

class UserUpload extends ModelUpload
{
    protected $model = \App\Models\User::class;

    protected $rules = [
        'name' => 'required|string',
        'email' => 'required|email|unique:users',
        'role' => 'nullable|in:admin,user',
    ];

    protected $map = [
        'name' => 'Name',
        'email' => 'Email',
        'role' => 'Role',
    ];

    protected $batchSize = 50; // Process 50 records at a time
}

Create a controller method to handle the upload:

use Atfromhome\LaravelModelUpload\Facades\ModelUpload;

public function upload(Request $request)
{
    $request->validate([
        'file' => 'required|file|mimes:xlsx,csv',
    ]);

    $upload = new UserUpload();
    $result = $upload->upload($request->file('file'));

    return response()->json($result);
}

Route the upload endpoint:

Route::post('/upload-users', [UserUploadController::class, 'upload']);

Implementation Patterns

1. Model Integration

Extend ModelUpload for each model you want to support. Key properties:

  • $model: The Eloquent model class.
  • $rules: Validation rules (same as Laravel’s FormRequest).
  • $map: Maps Excel headers to model attributes.
  • $batchSize: Optimize memory usage for large files.

Example for Product model:

class ProductUpload extends ModelUpload
{
    protected $model = \App\Models\Product::class;
    protected $rules = [
        'sku' => 'required|string|unique:products',
        'price' => 'required|numeric|min:0',
        'stock' => 'integer|min:0',
    ];
    protected $map = [
        'sku' => 'SKU',
        'price' => 'Price (USD)',
        'stock' => 'In Stock',
    ];
}

2. Workflow Patterns

A. Chunked Processing

For large files, use $batchSize to avoid memory issues. The package likely processes records in batches under the hood.

B. Custom Validation

Override rules() or validateRow() to add dynamic logic:

protected function validateRow(array $row): array
{
    $row['price'] = $row['price'] * 0.8; // Apply discount
    return $row;
}

C. Post-Import Actions

Use the afterImport hook to trigger actions (e.g., send notifications):

protected function afterImport(array $importedData)
{
    foreach ($importedData as $record) {
        Notification::send($record, new ProductImported($record));
    }
}

3. API/Controller Layer

Standardize upload handling in a base controller:

public function upload(Request $request, string $uploadClass)
{
    $request->validate(['file' => 'required|file|mimes:xlsx,csv']);
    $upload = app($uploadClass);
    return response()->json($upload->upload($request->file('file')));
}

Route dynamically:

Route::post('/upload/{uploadClass}', [UploadController::class, 'upload']);

4. Testing

Mock uploads with Laravel Excel’s FakeUploadedFile:

public function test_upload()
{
    Storage::fake('tmp');
    $file = UploadedFile::fake()->create('test.xlsx', 100, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');

    $response = $this->post('/upload-users', ['file' => $file]);
    $response->assertJson(['success' => true]);
}

Gotchas and Tips

Pitfalls

  1. Header Mismatches:

    • Ensure $map keys match exactly with Excel headers (case-sensitive). Use trim() if headers have inconsistent spacing.
    • Fix: Add a normalizeHeader method to clean headers:
      protected function normalizeHeader(string $header): string
      {
          return strtolower(trim($header));
      }
      
  2. Memory Limits:

    • Large files (>100K rows) may hit PHP’s memory_limit. Reduce $batchSize or increase the limit temporarily:
      ini_set('memory_limit', '512M');
      
  3. Unique Constraints:

    • Validation rules like unique:users,email may fail silently if the package doesn’t throw exceptions. Wrap uploads in a try-catch:
      try {
          $result = $upload->upload($file);
      } catch (\Exception $e) {
          return response()->json(['error' => $e->getMessage()], 422);
      }
      
  4. Timeouts:

    • Long-running imports may hit PHP’s max_execution_time. Use queues (see Extension Points).

Debugging Tips

  • Log Raw Data: Dump the first few rows to verify mapping:
    protected function beforeImport()
    {
        \Log::debug('First 5 rows:', array_slice($this->rows, 0, 5));
    }
    
  • Validate Rules: Test rules independently with Laravel’s Validator:
    $validator = Validator::make(['email' => 'invalid'], $this->rules);
    dd($validator->errors());
    
  • Check File Format: Ensure files are valid Excel/CSV. Use Laravel Excel’s Excel::toArray() to inspect:
    Excel::toArray([], $file)->first();
    

Config Quirks

  • Storage Paths: The package may default to storage/app/uploads. Override in config/laravel-model-upload.php:
    'storage' => 's3://your-bucket/uploads',
    
  • Temporary Files: Large files may clutter /tmp. Configure Laravel Excel’s temp directory:
    Excel::storeUsing(function ($file) {
        return Storage::disk('s3')->put('temp/' . $file->hashName(), file_get_contents($file->getRealPath()));
    });
    

Extension Points

  1. Queue Processing: Integrate with Laravel Queues to handle large files asynchronously:

    $upload->upload($file)->onQueue('uploads');
    

    Create a job:

    class ProcessUploadJob implements ShouldQueue
    {
        use Dispatchable, InteractsWithQueue, Queueable;
    
        public function handle()
        {
            $upload = new UserUpload();
            $upload->upload($this->file);
        }
    }
    
  2. Custom Importers: Extend the package’s importer class to add pre/post-processing:

    class CustomImporter extends \Atfromhome\LaravelModelUpload\Importers\ModelImporter
    {
        public function transform(array $row)
        {
            $row['created_at'] = now();
            return parent::transform($row);
        }
    }
    

    Bind it in AppServiceProvider:

    ModelUpload::macro('customImporter', function () {
        return new CustomImporter();
    });
    
  3. Webhooks: Trigger external APIs after import (e.g., sync with ERP):

    protected function afterImport(array $importedData)
    {
        Http::post('https://erp.example.com/sync', ['data' => $importedData]);
    }
    
  4. Localization: Customize error messages in $rules:

    'email' => 'required|email:rfc,dns,spoof|unique:users,email,'.$user->id.',id',
    

    Or override the package’s language file in resources/lang/en/validation.php.

Performance Tips

  • Database Indexes: Ensure columns used in $rules (e.g., unique) are indexed.
  • Batch Inserts: If using raw SQL, batch inserts reduce queries:
    DB::table('users')->insert($batch);
    
  • Caching: Cache validation rules if reusing the same upload class frequently:
    protected static $rulesCache = [];
    
    public function rules()
    {
        if (!isset(self::$rulesCache[$this->model])) {
            self::$rulesCache[$this->model] = $this->getRulesFromModel();
        }
        return
    
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor