filagora/filagora-forums
Filagora Forums is a Laravel/PHP package for adding a complete discussion forum to your app. It includes categories, topics, replies, moderation, role-based permissions, configurable models, migrations, and a clean Blade UI, making forum setup and customization straightforward.
Architecture fit. At v0.6.0 the package is no longer "a forum with an optional search add-on" — it is four independently adoptable subsystems: search (v0.5.0), and now attachments, mentions, and read tracking. The architectural pattern is consistent and reassuring: each feature is a service class (Attachments, Mentions, ReadTracking) plus Eloquent models, its own migration, config keys under a feature namespace, artisan commands where bulk work is needed, and for mentions/extensions the standard Laravel event + listener seam. Critically, all three new features are additive and individually switchable (mentions.enabled, mentions.mail.enabled, forums.orphaned_attachments, read_tracking.*), so a Laravel service can take read tracking without taking file uploads. The scope shift matters for planning: the package now reaches into the filesystem, the mail transport, image processing, the user table, and the named-route table of the host application. Each of those is a new coupling, and each is a place our platform team, not the forum team, has an opinion.
Integration feasibility. Mechanically this is still install, publish config, migrate, and optionally backfill — no framework surgery. The new work is in external dependencies and host-application obligations rather than in Laravel idiom. Attachments need intervention/image (and therefore GD or Imagick on every app server or worker), a configured disk with public serving, and a decision about thumbnails at upload time versus asynchronously. Mentions need a working mail transport and a route named by mentions.routes.thread — the package sends links to that route, so the host app must define it or the default email is broken. Read tracking needs read_tracking.baseline_attribute to name a real, monotonic column on the user model. authorizeUsing() on attachments is a genuinely useful extension seam for other packages' files, and the privacy export/erasure hooks across all three features are the right default for a package that stores personal data.
Technical risk. Risks now concentrate in six areas.
post_attachments and an object on a disk are two systems that can disagree. The failure that actually bites is a row without a file (serve-time errors) or a file without a row (silent storage growth). filagora:forums:prune-attachments plus forums.orphaned_attachments is a retention policy, not a reconciliation job — pruning must be proven not to delete a file that is referenced but was missed, and the "never used" erasure rule needs verification that "used" is defined the way legal expects.max_per_post is counted across edits with the row locked, which bounds the volume but not the surprise).forum_reads and thread_reads are unbounded-growth tables with no stated purge, and unreadAmong()/unreadThreads() inject correlated subqueries into listing queries — exactly the queries that must stay fast.filagora:adopt now expects nineteen tables and records six migrations, twenty/seven with mentions, twenty-one/eight with attachments. Any environment that adopted at v0.5.0 now sits below the expected counts after upgrade. Whether adopt is idempotent and how it behaves on a partially-adopted install is a blocking question, and the drop_indexes reference implies core 0.2.2 profile behaviour we must exercise.filagora/filagora-core ^0.2.2, and the package still reserves the right to rename models, config keys, and command signatures. The index schema risk from 0.5.0 is joined by a data-at-rest risk: attachment rows, mention rows, and read markers are all state we would have to migrate or discard on a breaking minor.Key questions.
filagora:adopt idempotent, and what does it do on an install adopted at v0.5.0 where the expected table and migration counts have now moved from sixteen-ish to nineteen/twenty/twenty-one?Attachments write to, is serving abstracted behind a route or a disk URL, and is there a documented reconciliation between post_attachments rows and objects on disk?mentions.routes.thread expect, and what is the observed failure mode if the route is undefined — failed send, queued retry, or silent drop?thread_reads and forum_reads, and what is the expected row growth per active user per month?read_tracking.baseline_attribute need to be monotonic, and what breaks if a user row is edited such that the baseline moves backwards?Stack fit. Still plain Laravel, but the compatibility surface has widened from "MariaDB and a search engine" to "MariaDB, a search engine, an object/filesystem disk, GD or Imagick, a working mail transport, and a user table with a usable baseline column." Read tracking and mentions have no search-engine or queue requirement stated, which keeps them cheap to adopt; attachments are the outlier because they introduce binary storage and image processing. Our standard service image should be checked for the GD/Imagick extension before any attachment work is scheduled, and services that already have an object-storage convention should use it rather than the default disk so backups and lifecycle rules are uniform.
Migration path. Additive, no breaking change signalled in these notes — but the migration numbering is the trap. This release adds the sixth, seventh, and eighth migrations, and filagora:adopt now asserts nineteen, twenty, and twenty-one tables depending on which features are enabled. The safe path is: pin core to ^0.2.2 explicitly, take the upgrade on a non-production copy of a real forum database first, and observe what adopt reports before and after. Treat the three migrations as separable — enabling only read tracking should mean only the sixth migration runs; confirm that migrations are feature-gated rather than all-or-nothing, because an all-or-nothing migration set forces us to take attachments to get read tracking.
Compatibility. Three axes now. First, package pinning: caret-to-minor on both filagora/filagora and filagora/filagora-core, and a rule that core's floor moves with the forum package's floor. Second, database: unchanged from 0.5.0 (MariaDB FULLTEXT default; MySQL needs validation or search.fulltext off), plus the new read-tracking subquery load on listing queries, which should be measured on production-shaped data rather than assumed. Third, host-application obligations: a named route for mention emails, a storage disk, the user baseline column, and the image extension. These are configuration items that will silently degrade if missed — an undefined route or a missing column should be caught at deploy time, not at first use.
Sequencing. The features are independent, so sequence by risk and by reversibility, not by release order.
mentions.mail.enabled false and in-app only, validate recipient visibility against the policy path, then enable mail for a limited audience.Maintenance. Four feature surfaces and two packages on a pre-1.0 cadence. The maintainable posture is to adopt features one at a time and keep each behind its own config switch, so an upgrade can be taken with the newest feature off. Two new maintenance duties arrive with attachments: storage lifecycle (retention, backups that include binaries, and a restore test that proves DB and disk are restored to the same point) and the prune command's schedule. Read tracking adds a growth-watch duty, since nothing in these notes describes a purge. Mentions adds a mail-deliverability dependency that previously did not exist for this package. The adopt table-count assertions should be captured in our environment documentation, because they will change again and the error message will be the first thing an operator sees.
Support. New first-line questions, each needing a runbook line: "my upload was refused" (hourly limit, size/type validation, or AttachmentRefused), "the file 404s" (storage/row divergence — escalate), "why wasn't I told I was mentioned" (author never notified, duplicate suppressed, no visibility at extraction, max_per_post exhausted across edits, or mail switched off), "the link in my mention email is broken" (undefined or renamed mentions.routes.thread), "why is that thread still unread" (hand-made unread flag beats read times by design), and "mark all read is slow" (bulk write footprint). Two escalation triggers should be written down as incidents, not tickets: a user receiving a mention notification for a thread they cannot open, and an attachment being served to someone who cannot open the post. Support also needs to know that a privacy erasure request now spans three subsystems and a binary store.
Scaling. The scaling story has moved away from search. Attachments scale with bytes: index size grows with uploads, thumbnail generation consumes CPU at upload time if synchronous, and serving needs to come off the application servers (CDN or signed URLs) before volume makes per-request PHP file serving the bottleneck. Download counting is a write per download and will be the first attachment-related hotspot. Mentions scale with fan-out: one post can produce up to mentions.max_per_post notifications, each possibly an email, and the row lock on the post serialises concurrent edits — fine on a normal forum, a contention point on a hot thread. max_per_post is the main lever and should be set deliberately rather than left at default. Read tracking scales with page views: it converts reads into writes at the rate of thread views plus mark-all-read bursts, and its tables have no stated ceiling. unread_max_lookback_days bounds the "what's new" query but not the table. Search scaling is unchanged from the v0.5.0 assessment.
Failure modes.
filagora:forums:prune-attachments deletes a file that is still referenced; user-visible data loss and unrecoverable without a backup.thread_reads/forum_reads grow without bound and degrade unreadAmong().filagora:adopt to misreport on an existing install; combined with pre-1.0 renames, forces a data migration we did not plan for.Ramp-up. The v0.5.0 estimate of roughly a sprint for search holds for search alone. v0.6.0 does not add a sprint's worth of install work — each feature is small in isolation — but it adds three separate verification tasks, and the verification, not the install, is the cost. Budget roughly a sprint per feature for a team already fluent in Laravel: read tracking is the cheapest and teaches the listing-query hot path; attachments is the most expensive because it needs a disk decision, an image-extension check, a prune rehearsal, and a binary-inclusive restore test; mentions is the slowest to clear because it needs the route wired, mail validated, and a visibility-parity test before any email is enabled. Recommended posture: ship read tracking in the first cycle, attachments behind a per-user or per-forum flag in the second, and mentions in-app only before mail. Do not take all three in one release window alongside an unrelated platform change — the failure modes above are individually survivable and collectively hard to attribute.
How can I help you explore Laravel packages today?