juanborras's avatar

Filament Importing MorphTo relationship

Dear All,

I have a Customer -> Address MorphTo relationship, any idea on how to build the importer?

Thanks!

0 likes
3 replies
LaryAI's avatar
Level 58

Certainly! Here's how you can approach building an importer for a MorphTo relationship using Filament in Laravel.

Understanding the Problem

  • Customer has an Address relationship, where Address is morphed to various models (MorphTo).
  • You want to import data (presumably from CSV/Excel) such that addresses are correctly associated with the customers via the MorphTo.

Solution Overview

When importing, you need to ensure:

  • The addressable_id and addressable_type fields are set correctly in the addresses table.
  • The import process knows which model (in this case Customer) the address belongs to.

Assuming your addresses table looks like:

Schema::create('addresses', function (Blueprint $table) {
    $table->id();
    $table->morphs('addressable'); // addressable_id, addressable_type
    $table->string('address');
    // ... other fields
});

And your Customer model:

public function addresses()
{
    return $this->morphMany(Address::class, 'addressable');
}

Example Importer Using maatwebsite/excel with Filament

Let's use maatwebsite/excel, which is a common package for importing/excel data in Laravel ecosystems. If you're using Filament Excel, it leverages this under the hood.

AddressImport.php:

namespace App\Imports;

use App\Models\Customer;
use App\Models\Address;
use Maatwebsite\Excel\Row;
use Maatwebsite\Excel\Concerns\OnEachRow;
use Maatwebsite\Excel\Concerns\WithHeadingRow;

class AddressImport implements OnEachRow, WithHeadingRow
{
    public function onRow(Row $row)
    {
        $row = $row->toArray();

        // Lookup Customer
        $customer = Customer::where('email', $row['customer_email'])->first();

        if ($customer) {
            $customer->addresses()->create([
                'address' => $row['address'],
                // add other address fields
            ]);
        }
    }
}

Sample CSV Format:

customer_email,address
[email protected],123 Main St
[email protected],456 Elm Ave

When the import runs:

  • It locates the customer by email.
  • Calls $customer->addresses()->create([..]), which will automatically set the correct addressable_id and addressable_type.

Using Filament Plugin (eg. Filament Excel)

If you're using Filament Excel:

In your Filament Resource for Address, set up the importer similarly.

use App\Imports\AddressImport;

public static function getImportAction(): ImportAction
{
    return ImportAction::make()
        ->importer(AddressImport::class);
}

Tips

  • Make sure your input file uniquely identifies the Customer (or any morphable model).
  • If addresses can belong to other models, expand logic to check for different model types using a model_type column in your CSV.

Summary

  1. In your importer, loop through rows.
  2. Lookup the related model (Customer).
  3. Use the relationship ($customer->addresses()->create()) to create the address. This sets the MorphTo fields automatically.

If you need to support multiple models (not just Customer), add logic to detect addressable_type from your import file.


Let me know if you have a more specific use-case or need to handle multiple morph types!

imranbru's avatar

In your Importer class, the easiest way is to map the owner's ID from your CSV and then use the beforeCreate hook to assign the morph columns manually

Please or to participate in this conversation.