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

Laravel Chat Laravel Package

sevenspan/laravel-chat

sevenspan/laravel-chat is a Laravel package for adding user-to-user chat to your application. It includes models, migrations, and controllers for conversations and messages, helping you integrate private messaging quickly with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is small enough that setup is quick, but also young enough (18 stars, no dependents) that you should treat it as a starting point rather than a finished product.

  1. Install and publish. composer require sevenspan/laravel-chat, then publish the config and migrations (php artisan vendor:publish --tag=laravel-chat-config and the migrations tag — check config/chat.php after publishing to confirm the exact tag names). Run php artisan migrate.
  2. Wire the User model. The package ships a trait (typically HasChats or similar) that gives your model chats(), messages(), and helper methods for creating and enumerating conversations. Add it to App\Models\User before doing anything else — most of the public surface hangs off this trait.
  3. Configure storage. Set the chat upload disk in config/chat.php (local vs s3). The S3 path expects FILESYSTEM_DISK=s3 plus the usual AWS_* envs; if you're not on S3, leave it as public and make sure php artisan storage:link has been run.
  4. Read the source first. With this few stars there's no meaningful docs ecosystem. Point new team members at src/Models, src/Traits, and src/Contracts — that's where the actual behavior lives. The README is a rough starting point, not a reference.
  5. First use case to validate: create a one-to-one chat between two users, send a message with an attached document, mark it read from the other side, and confirm unreadCount() reflects correctly. Once that loop works end-to-end, the rest of the package's surface is variations on the same theme.

Implementation Patterns

Chat creation — keep it behind a service. Both one-to-one and group chats are usually created through a dedicated method on the trait. Wrap that in a ChatService so you can enforce "don't create duplicate DMs between the same pair," add participants in bulk, and attach metadata (name, avatar for groups) that the package itself doesn't care about. The raw package method will happily create two chats between the same users if you call it twice.

Polymorphic participants vs. user IDs. Depending on the version, participants may be stored as user IDs or through a pivot. If you need role-based membership (owner/admin/member for groups) or non-user participants (admins, support bots), add a chat_participants table of your own and treat the package's membership as the "core" set. Don't extend the package's migrations directly — you'll lose them on the next upgrade.

Attachments. Document sharing is the headline feature, so treat uploads as a first-class concern. The pattern that ages well: accept the upload in your own controller, store via Storage::disk(config('chat.storage_disk'))->putFile(...), then pass the resulting path/metadata into the package's message-create call. That way, when you need virus scanning, signed URLs, or size limits, you control the boundary. If you hand the raw UploadedFile straight to the package you lose those hooks.

Read/unread counts. The package tracks read state per participant. Two patterns are common:

  • For inbox lists, call the package's unread-count method per chat — fine for small lists, painful at scale.
  • For anything user-facing with more than a few dozen chats, materialize a chat_read_state (user_id, chat_id, last_read_message_id, unread_count) table updated on send and on read, and refresh it via a queued job. Let the package's counts be a fallback, not the primary read path.

Broadcasting. If the package dispatches events (check src/Events), wire them into your BroadcastServiceProvider and expose them on private channels keyed by chat ID. Don't broadcast on public channels — read receipts and message previews leak content. If it doesn't ship events, that's the first thing to add yourself: after Message::create, dispatch MessageSent, and let a listener broadcast.

Notifications. Pair the package with Laravel's notification system rather than relying on it for delivery. Send a NewChatMessage notification (mail + database + broadcast) from a listener on the send path, so the chat package stays focused on storage and the "notify" policy stays in your app.

Gotchas and Tips

  • Very low adoption. 18 stars and zero dependents means no community answers when something breaks. Pin the version in composer.json and be prepared to fork. Read every migration before running it in production — collision with existing chats/messages tables is a real risk if you've prototyped your own chat previously.
  • Read-count accuracy under concurrency. Marking-as-read and counting unread rarely survive fast message bursts without care. Wrap send + read-state update in a transaction and, if accuracy matters, recompute counts rather than incrementing them.
  • Storage disk is global. The config points at one disk. If you want profile-adjacent chats on S3 but tenant uploads on local (or vice versa), you'll need to override the storage resolution — don't assume per-chat disk configuration exists.
  • File ownership and cleanup. Deleting a message doesn't necessarily delete its attached file. Add a model observer or listener that removes the storage object before the row, otherwise S3 bills quietly grow.
  • Group permissions are minimal. The package models membership, not authorization. Add policies (ChatPolicy::view, ::send) yourself and use Gate::authorize in controllers; don't rely on the package to reject writes.
  • Pagination. Message listings need explicit pagination — default get() behavior on a long chat will load the entire history. Always use the package's paginated query or ->paginate() on the relation, and load messages in reverse chronological order for the UI.
  • Debugging tip. If messages appear sent but the recipient shows nothing, check (a) the participant row was actually created for the recipient, (b) your unreadCount query is scoped to the right user, and (c) any broadcast listener is authenticated on the private channel. Ninety percent of "chat doesn't work" reports are one of those three.
  • Extension points to plan for: a MessageObserver (for search indexing, moderation, notifications), a ChatPolicy (for group authorization), and a custom ChatRepository wrapping the package's queries if you need to swap in read-replica connections later. Keep all three in app/, never in vendor/.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console