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

Filament Max Chat Laravel Package

geekcodev/filament-max-chat

Filament plugin for an operator chat with MAX messenger users. View dialogs with unread badges, reply with HTML formatting and media attachments, receive real-time Echo/Reverb updates with a poll fallback, and configure permissions, channel, disk and navigation via config.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Laravel package for MAX chat messaging; v1.1.5 is a pure performance patch (one additive migration), so upgrading is composer update + php artisan migrate. No new env vars, config keys, translation keys, or public signature changes.

Where to look first:

  1. MaxMessageService::totalUnreadCount() — the single source of truth for the unread badge and the JSON unread counter. Call this instead of writing your own where direction = 'in' and read_at is null query.
  2. UnreadCountController — the JSON endpoint behind the panel navigation badge; mirror its query shape if you build your own counters.
  3. MaxMessageService::markRead() — marks a chat read via max_chat_id plus the same direction/read_at predicate.
  4. The migrations directory, specifically 0000_02_000003_add_unread_index_to_max_chat_messages.php, which adds max_chat_messages_unread_index on (direction, read_at).

First use case: render the panel navigation badge on a page, hit the JSON unread endpoint, then mark one chat read and confirm the badge decrements. Then run EXPLAIN on the unread query and confirm max_chat_messages_unread_index is used — that single check validates you got the whole point of this release.

Implementation Patterns

Always go through the service for unread counts. The new composite index (direction, read_at) covers exactly the predicate direction = 'in' and read_at is null. If you hand-roll the same query in a dashboard widget or an API resource, you still get index coverage — but if you add extra columns to the select or where, you may fall back to a scan. Prefer totalUnreadCount() and cache the result at the component level.

Keep markRead() on the existing path. It is deliberately keyed by max_chat_id and continues to use the existing (max_chat_id, created_at) index. Don't refactor it to filter by read_at first "for consistency" — that would trade a cheap index seek for the new index's wider scan.

Badge on every render. The navigation badge is computed on each page render, which is why the missing index hurt so much. With the index in place this is cheap, but on high-traffic dashboards consider a short-lived per-user cache (a few seconds) or compute it in a view composer so multiple layouts don't each trigger the query.

Deploy order for Octane. Run php artisan migrate as a separate step, then php artisan octane:reload so workers pick up new code. The release notes describe workers being pinned by full scans until /up failed and the container restarted — reloading without migrating leaves you with the old plan and the same failure mode.

Host apps that already added an index. up() guards with Schema::hasIndex, so re-running is safe. Keep the name max_chat_messages_unread_index if you customize or copy the migration; if you fork the migration, preserve the guard so downstream installs that already indexed the table don't fail.

Multi-database installs. The index is a plain composite rather than a partial index specifically for portability across SQLite, PostgreSQL, and MySQL. If you were hoping for WHERE read_at IS NULL compaction, you won't get it from this package — add it yourself only if you're MySQL/Postgres-only and can maintain a divergent migration.

Testing your integration. The package ships MaxChatMessagesSchemaTest covering index presence, down() removal, re-creation, and idempotency. If you override migrations in a host app, add an equivalent assertion in your own suite.

Gotchas and Tips

  • Index creation on a large table is itself the risk. This patch exists because the table got big; CREATE INDEX on that same table can take time and, on older MySQL, lock writes. Plan the first deploy (maintenance window or online DDL) rather than treating it as a no-op migration.
  • down() drops the index. Rolling back on a mature install silently returns unread counts to full scans. That is the original incident, reintroduced — avoid rollbacks of this migration in production.
  • The hasIndex guard is name-based. If your host app already created an equivalent index under a different name, the guard won't see it and you'll end up with two indexes on nearly the same columns. Check SHOW INDEX after migrating.
  • Verify the plan, don't assume. Run EXPLAIN (or EXPLAIN ANALYZE) on both the badge query and the JSON controller query in staging, with realistic row counts. A correct index plus a bad query shape still scans.
  • Watch for the symptom recurring. Pre-1.1.5 the failure surfaced as Octane worker exhaustion and container restarts on /up, not as an obviously slow endpoint. If /up flaps under tab-switching load, check unread-count query plans before blaming infrastructure.
  • composer audit behind restricted networks. The package's own gate needed COMPOSER_IPRESOLVE=4 to reach Packagist. If you run the package test suite or audit in a locked-down CI, set that env var rather than disabling audit.
  • No BC surface to worry about. Config defaults, public method signatures, and translation keys are untouched. The only upgrade action is migrate; nothing to republish or re-translate.
  • Coverage caveat is upstream, not yours. The release notes mention the CI "clean resolve" step wasn't run locally due to host disk space. That's a packaging-environment detail; it doesn't change the artifact, but it's a reason to run your own composer install in a clean directory as part of the upgrade smoke test.
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel