Courses

Creating CRM with Filament 3: Step-By-Step

Custom Fields for Customers

Summary of this lesson:
- Building custom fields system with pivot table
- Creating CRUD for field management
- Adding dynamic custom fields to customer form
- Implementing flexible display in customer view

Quite often, CRMs do not fit in the pre-defined fields. This is where Custom Fields come in handy, as they allow users to set up their own fields for the CRM and fill Customer profiles with them:

In this lesson, we will do the following:

  • Create a Custom Field database table and Model
  • Create a pivot table for the Custom Field and Customer relationship
  • Create a pivot Model type for Filament to better handle the relationship
  • Create simple Custom Field seeders
  • Create a Custom Field CRUD (Filament Resource)
  • Add Custom Field to the Customer Resource via Repeater Component
  • Display Custom Fields on the Customer View page - we will generate them dynamically

Preparing Database, Models and Seeders

Let's start by creating our Custom Fields database. It will have just one field - name:

Migration

Schema::create('custom_fields', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});

Next, we know that this is going to be a many-to-many relationship, so we need a pivot table:

Migration

use App\Models\Customer;
use App\Models\CustomField;
 
// ...
 
Schema::create('custom_field_customer', function (Blueprint $table) {
$table->id();
$table->foreignIdFor(Customer::class)->constrained();
$table->foreignIdFor(CustomField::class)->constrained();
$table->string('value');
$table->timestamps();
});

Then, we can create our Models:

app/Models/CustomField.php

class CustomField extends Model
{
protected $fillable = [
'name'
];
}

And a pivot Model (Filament uses it to better handle the relationship):

app/Models/CustomFieldCustomer.php

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\Pivot;
 
class CustomFieldCustomer extends Pivot
{
public function customer(): BelongsTo
{
return $this->belongsTo(Customer::class);
}
 
public function customField(): BelongsTo
{
return $this->belongsTo(CustomField::class);
}
}

The last Model to update is the Customer Model, as we need to define the relationship:

Note: This is not a many-to-many relationship, as we use a pivot Model. So we need to use HasMany instead of BelongsToMany. It works the same as many-to-many, but now with an intermediate model!

app/Models/Customer.php

public function customFields(): HasMany
{
return $this->hasMany(CustomFieldCustomer::class);
}

Now, we can create our seeders:

database/seeders/DatabaseSeeder.php

use App\Models\CustomField;
 
// ...
 
public function run(): void
{
// ...
 
$customFields = [
'Birth Date',
'Company',
'Job Title',
'Family Members',
];
 
foreach ($customFields as $customField) {
CustomField::create(['name' => $customField]);
}
}

Running migrations and seeds:

php artisan migrate:fresh --seed

Should now give us a few Custom Fields in the database:


Creating Custom Field CRUD

We created the Resource CRUD with this command:

php artisan make:filament-resource CustomField --generate

Then, all we had to do - was move...

The full lesson is only for Premium Members.
Want to access all 17 lessons of this course? (97 min read)

You also get:

  • 73 courses
  • Premium tutorials
  • Access to repositories
  • Private Discord