Our Customer needs some documents to be uploaded. These can range from simple information sheets to signed PDF documents. We need to be able to upload them and add notes to them, just like this:

In this lesson, we will do the following:
- Create Documents database table, model
- Add Documents to the Customer form - only for edit page
- As a bonus, we will clean up the form a bit
- Add Documents to the Customer view page as downloadable links
Creating Database Table and Model
Our Documents will have the following fields:
-
id -
customer_id -
file_path -
comments(nullable text)
Let's start with the migration:
Migration
use App\Models\Customer; // ... Schema::create('documents', function (Blueprint $table) { $table->id(); $table->foreignIdFor(Customer::class)->constrained(); $table->string('file_path'); $table->text('comments')->nullable(); $table->timestamps();});
Then, we will create the model:
app/Models/Document.php
use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\Relations\BelongsTo;use Storage; class Document extends Model{ protected $fillable = [ 'customer_id', 'file_path', 'comments' ]; protected static function booted(): void { self::deleting(function (Document $customerDocument) { Storage::disk('public')->delete($customerDocument->file_path); }); } public function customer(): BelongsTo { return $this->belongsTo(Customer::class); }}
Quick note: Look at our deleting observer - we delete the file from the storage when the document is deleted. This is an excellent practice to follow.
And lastly, we need to tie our Customer model to the Document model:
// ... public function documents(): HasMany{ return $this->hasMany(Document::class);}
Adding Documents to the Customer Form
Adding Documents to the Customer form is...
before the facelift of app/Filament/Resources/CustomerResource.php you need to php artisan migrate the relationship is ->relationship('customerDocuments') (not ->relationship('documents') )
Updated the relationship name. It slipped in editing proccess and it should be
documentseverywhere.i get an error in the pipeline-stage-history-list.blade.php foreach() argument must be of type array|object, null given
Could you add some code example? There might be something wrong with the relationship or data loading
adding an if before the foreach solves the problem in the resources/views/infolists/components/pipeline-stage-history-list.blade.php
@if(!empty($getState()))
In that case, your observer has failed to create a fresh state OR you forgot to freshly migrate the database.
By default, it should have a state as soon as a customer is created by using an observer
i can see the documents section but i cann't see any document and i uploaded 2 files and i can see them if i edit the customer
There might be issue with your relationship names. Please change all of them to
documentsand it should work. If it does not - would be great to see some code examples.Modestas, how about use RelationManager in place of Repeater to deal with documents? Then we can add tags, use default table search, actions and so on. How this can be done with infolists?
Personally, I would not use relation manager here. But if you do want to use it - infolist should work as is. it's just a relationship after all, and we are doing cuatom data display (from a relationship)
love the simplicity of how documents are added! Looks really clean. a few questions:
Thanks again for everything and I have to say (having two small kids) that I love this text format for learning. It is perfect!
Hi, first of all - thank you for the kind works!
Now onto your questions:
thanks for the fast reply! Quick follow up question, I am indeed considering using spatie media library but I dont need all those extra functions and need support for multiple different filetypes and I dont know if that would work.. I read the docs but couldnt find anything about enabling different file types.
Do you have any (filament) example projects with spatiemedia library planned?
With spatie media library you can upload whatever you want. I've used it in many projects to upload documents, invoices and so on!
As for example, not sure right now (replying from mobile :) ) but we should have some examples of media upload overall
Thanks Modestas! Thats great to hear, will try it out. :)
If your uploaded files are not found, you may not have a symbolic link from your public folder to your storage folder. You can run the following to fix it: