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 Lms Laravel Package

tapp/filament-lms

Filament LMS brings a complete learning management system to your Filament admin panel. Manage courses, lessons, modules, students, enrollments and progress from one familiar Laravel interface—ideal for building online course platforms without extra tooling.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and publish its assets before touching any models:

composer require tapp/filament-lms
php artisan vendor:publish --tag="filament-lms-config"
php artisan vendor:publish --tag="filament-lms-migrations"
php artisan migrate

Register the plugin in the panel provider that should host the LMS admin surface:

use Tapp\FilamentLms\FilamentLmsPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugin(FilamentLmsPlugin::make());
}

Where to look first, in this order:

  1. README.md for the canonical install snippet and any required User contract/trait.
  2. config/filament-lms.php after publishing — this tells you which models, disks, and route prefixes are swappable.
  3. database/migrations/ — the schema is the real API. Course → lesson → enrollment → progress is the mental model you need.
  4. src/Models/ and src/Filament/Resources/ — resources reveal the expected relationships and authorization behaviour.
  5. src/FilamentLmsPlugin.php — every ->...() method there is an extension point.

First use case to validate the install: log into the panel, create a Course, attach two Lessons, enrol your own user, and mark one lesson complete. If the progress percentage updates in the admin table, the package is wired correctly and you can start integrating it into your domain.

Implementation Patterns

Separate admin and learner surfaces. Keep the package's resources in an admin panel and build learner-facing pages yourself (or in a second panel). The package's Filament resources are written for management CRUD; trying to reuse them as a student UI fights the defaults.

Treat the models as your domain layer. For custom frontend work, depend on the package models directly rather than the Filament resources:

$course->lessons()->orderBy('position')->get();
$enrollment = $user->enrollments()->firstOrCreate(['course_id' => $course->id]);

Wrap enrolment and completion in your own actions/services so you have one place to fire notifications, award certificates, or sync to a CRM.

Use policies, not resource-level conditionals. Publish/generate policies for the LMS models and register them normally. Filament will respect viewAny, create, update on resources, and you get the same rules for free on any custom pages.

Eager-load for list screens. Lesson and enrolment tables typically traverse course, user, and progress relations. Add ->modifyQueryUsing(fn ($query) => $query->with(['course', 'user'])) on tables, or override the resource's getEloquentQuery().

Customise via schema/table callbacks where available. Most Tapp plugins expose ->form(fn (Form $form) => ...) or resource-level static methods. Prefer these over forking the resource classes — you keep upstream fixes.

Multi-tenancy. If your panel uses Filament tenancy, confirm the LMS models carry team_id/tenant_id (check migrations). Add a global scope in a model extension if not, otherwise courses leak across tenants.

Testing. Follow the repo's own conventions — Pest with uses(RefreshDatabase::class), test()/expect(), and beforeEach(). Build a small factory helper that creates a course with lessons plus an enrolled user; nearly every LMS test starts there.

Run the tooling the maintainers run:

./vendor/bin/pint
./vendor/bin/phpstan analyse

Do this before every PR; the CI expects clean style and static analysis.

Gotchas and Tips

  • Publish before migrate. Running migrate without publishing migrations silently gives you no LMS tables. Publish, review the migration filenames, then migrate.
  • Config cache. After changing config/filament-lms.php run php artisan config:clear (and filament:optimize-clear if you use Filament's optimisation commands). A stale cached config is the most common "my disk/model override isn't applied" cause.
  • Model swapping. If the config exposes model bindings, swap the class and verify the migrations match your table names. A swapped model without the expected relations fails at runtime, not at boot.
  • Filament major version drift. Pin the package version and check its composer.json constraint against your Filament version. A Filament 3 → 4 jump in a plugin this small can lag; test panel registration after any Filament upgrade.
  • Completion idempotency. Progress writes are often triggered from multiple places (button, event listener, API). Make completion a firstOrCreate/upsert, not a create, or you'll get duplicate progress rows and inflated percentages.
  • Authorization gaps. Filament resources are guarded; your custom learner routes are not. Add explicit Gate::authorize('view', $course) calls, especially for lesson content and downloads.
  • Storage disks. Course images and lesson media usually go through a configurable disk. In production set the disk explicitly and check that URLs are generated through Storage::disk(...)->url() rather than hardcoded paths.
  • N+1 on progress. Rendering a course outline with per-lesson completion status is the classic N+1. Load the user's progress rows once and key them by lesson_id.
  • Route/model binding. If lessons are bound by slug in learner routes, ensure the migration has a unique index on the slug column — otherwise duplicate slugs break resolveRouteBinding.
  • Extension points to prefer, in order: plugin config → resource schema/table callbacks → custom Filament page extending the package page → model subclass → fork. Forking is last resort for a 24-star package; you'll be maintaining it.
  • Debugging checklist: php artisan route:list | grep lms, php artisan about, verify the plugin is in the panel's ->plugin() chain, and dd() inside the resource's getEloquentQuery() to confirm scoping. If resources don't appear in navigation, it's almost always plugin registration or policy denial.
  • Low ecosystem maturity. With a single-digit dependent count, expect to read source rather than docs. Keep your integration thin and behind your own services so a breaking minor release is a one-file fix.
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib