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 ofBelongsToMany
. 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...