Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filagora Messages Laravel Package

filagora/filagora-messages

A Laravel and Filament package for adding private messaging to your application. It provides conversations, message threads, and a clean UI for sending and receiving messages between users, with straightforward installation and integration into existing Filament panels.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package alongside your Laravel app and publish what it needs:

composer require filagora/filagora-messages
php artisan vendor:publish --tag=filagora-messages-config
php artisan vendor:publish --tag=filagora-messages-migrations
php artisan migrate

Look here first, in this order:

  1. config/filagora-messages.php — conversation/message models, table names, and the guard/user resolver used for membership checks.
  2. The published migrations — message and conversation tables, and (if you publish them) the forums attachment extension migration.
  3. The PrivateMessage model and its relations — conversation(), sender(), and now attachments().
  4. The filagora:* commands registered by the service provider, particularly filagora:adopt and filagora:messages:link-attachments.

First real use case: send a message inside a private conversation, render it in a thread view, then add a file upload to the compose form. Once that works end-to-end, wire in the attachment authorization (MessageAttachmentAccess) before you expose any download route.

Attachments are an optional integration: they light up only when filagora/filagora-forums ^0.6 is installed. You can ship messaging first and add forums later — the link-attachments command exists precisely so you can retrofit the columns onto an already-running install.

Implementation Patterns

Sending and replying. Message sends and replies both go through the same attachment-claiming step (ClaimMessageAttachments): the sender's own waiting files that the message body references are claimed for that message. In practice this means your flow is "upload file → keep it unclaimed → submit the message body referencing it → package claims it." Don't try to attach files after the message is created and expect them to appear; the claim happens at send time.

Render the thread with its attachments. Eager-load to avoid N+1 on long threads:

$conversation->messages()
    ->with(['sender', 'attachments'])
    ->latest()
    ->paginate(50);

Guard the relation in views when forums isn't installed — attachments() may resolve to an empty collection, but your view shouldn't assume the table exists if you run mixed environments (e.g. a subset of apps without forums).

Authorize downloads via MessageAttachmentAccess. Don't roll your own "is the current user in this conversation" check in the controller. The access class is what enforces "only people still in the conversation" — which matters when members are removed. Route the download through it:

abort_unless(MessageAttachmentAccess::allows($attachment, $user), 403);

Extending an existing forums install. Three migration paths, pick based on your situation:

  • Fresh install with forums already present: copy the migration from database/migrations/forums into your app's migrations, ensuring its timestamp sorts after forums' own attachments table migration.
  • Forums already migrated in production: run php artisan filagora:messages:link-attachments to add private_message_id and private_conversation_id in place.
  • Half-applied / uncertain state: let AttachmentLinks run — it installs the columns safely from any partially-complete state.

Schema-extension awareness. Once the columns exist, the forums snapshot must accept a table that has extra columns. The package declares them as a schema extension of the forums snapshot so filagora:adopt doesn't choke on the unknown columns. If you maintain your own adopt/snapshot tooling, mirror that declaration.

Integration tip. Keep the attachment-claim step inside the same transaction as message creation if you care about "message sent but file unclaimed" being impossible. The claim is the only thing tying a file to a message, so a partial failure leaves an orphaned waiting file rather than a broken message.

Gotchas and Tips

  • Foreign keys are cleared, not cascaded. Deleting a message or conversation nulls private_message_id / private_conversation_id on the attachment row rather than deleting the file. Your attachments() relation must therefore tolerate nulls, and you should decide explicitly what happens to the underlying file (storage cleanup job, retention policy). Don't assume deletion cascades.
  • Migration ordering is the #1 failure mode. If the extension migration runs before forums' attachments table exists, the FK targets a missing table. Check timestamps first when you see "table not found" or "no such table" during migrate. On SQLite this is especially easy to hit in tests.
  • The migration is a no-op without forums. If you publish it and forums isn't installed, nothing happens — which is correct, but it also means no error to warn you that attachments are silently unavailable. Verify class_exists of the forums attachment model in a health check if this matters.
  • filagora:adopt acceptance isn't automatic for other tables. Only the declared extension is tolerated. If you add your own columns to the same table, expect adopt to complain unless you extend the snapshot yourself.
  • Silent no-op claims. If the message body doesn't actually reference the waiting file, the claim finds nothing and you get a message with zero attachments and no exception. Assert on attachment count in tests after send rather than trusting the UI.
  • Don't authorize with membership alone. A user removed from the conversation after the message was sent must lose access to attachments. MessageAttachmentAccess encodes that; ad-hoc $conversation->hasMember($user) checks in a download controller will drift.
  • Version constraint. The integration is declared as ^0.6 on forums and is suggested, not required. Pin it explicitly in your composer.json if you rely on attachments — a resolution that pulls an older forums version will leave the extension columns orphaned and the claim flow inert.
  • Debugging checklist for "attachment not showing": (1) does the row have a non-null private_message_id? (2) does the body actually reference the file? (3) was the file uploaded by the sender (only the sender's own waiting files get claimed)? (4) is the viewer still a conversation member per MessageAttachmentAccess?
  • Extension points. AttachmentLinks (idempotent schema reconciliation) and ClaimMessageAttachments (claim policy) are the two places to look if you need custom behavior — subclass or decorate these rather than editing published migrations or models.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource