earmsby's avatar

two importers for same model?

I'm trying to implement two separate importers on the same model (Contract). I want one to create new records only and the other update existing records only. I know you can combine these, but the client I'm building for needs these to be separated.

What is the best approach for this? FWIW, I've already fully built the importer to create new records. Now I'm looking to build a second importer which only updates Contracts.

0 likes
4 replies
LaryAI's avatar
Level 58

Certainly! Here's a clear approach for having two separate importers for the same Contract model: one for creating and one for updating. You might be using a package like Laravel Excel for imports, but the architectural pattern stands with or without a package.


Approach Summary:

  1. CreateNewContractsImporter: Only creates new Contract records, ignores existing ones.
  2. UpdateExistingContractsImporter: Only updates existing Contract records, ignores new ones.

Your first is already built (CreateNewContractsImporter). Here’s how you could structure the update-only importer:


Update Only Importer

use Maatwebsite\Excel\Concerns\ToModel;
use App\Models\Contract;

class UpdateExistingContractsImporter implements ToModel
{
    public function model(array $row)
    {
        // Assume your unique identifier is in $row[0], adjust as necessary
        $contract = Contract::where('contract_number', $row[0])->first();

        // Only update if contract exists
        if ($contract) {
            $contract->update([
                'field1' => $row[1],
                'field2' => $row[2],
                // ... other fields
            ]);
        }

        // If you always need to return a model or null:
        return null;
    }
}

Tips

  • Make sure the "unique identifier" is the same as used in your system (id, contract_number, etc.).
  • No new record is created here; .update() only fires for existing.
  • Returning null (or just void) is okay if your importer supports it―otherwise, return the updated model.
  • If you need validation, consider implementing WithValidation or similar concerns.

Optional: Validation to Ensure No New Contracts

If you want to be extra safe:

if (!$contract) {
    // Optionally, log or collect errors about "missing contracts"
    return null; // Or throw an exception if you prefer
}

Summary

  • Keep two separate importer classes, each with a very explicit, limited responsibility.
  • Creation: Only insert new records (skip/update errors if record exists).
  • Update: Only update existing records (skip/memo errors if not found).

This maximizes clarity and keeps your logic separation just as your client requested.


If you need a more specific example (like for a plain PHP upload script), let me know!

martinbean's avatar

@earmsby It would help if you clarified what you mean by “importer”. As if the importers are just code, then the code will do whatever it instruct it to do.

So what do you mean by “importer”? Custom code? A third-party package? Something else?

earmsby's avatar

Yes, it's a filament importer. I'm not sure the code from LarryAI is what I'm looking for, so I'm working through creating 2 importers via the "make:filament-importer" command and then modifying the resulting importer code.

Please or to participate in this conversation.