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

Lms Laravel Package

eren/lms

eren/lms is a Laravel package for adding learning management features to your app: courses, lessons, enrollments, progress tracking, and quizzes. It includes migrations, Eloquent models, and configurable routes to get a simple LMS running quickly.

View on GitHub
Deep Wiki
Context7

Getting Started

Confirm distribution first: v1.8 is a small PR-and-dependabot release with no changelog detail, so verify whether the package is on Packagist or must be pulled from the repo directly.

composer require noumanahmad448/lms   # or add a vcs repository + "dev-main"/"^1.8"
php artisan vendor:publish --provider="NoumanAhmad448\Lms\LmsServiceProvider"
php artisan migrate

Look at, in this order:

  1. config/lms.php (or whatever the published config is named) — this is where table prefixes, model overrides, and route middleware are almost always exposed.
  2. The published migrations — they tell you the real domain model (courses → sections/lessons, enrollments, progress) faster than any docblock.
  3. routes/ in the package source — the route names and middleware groups reveal how much authorization is already enforced versus left to you.

The first thing to build: a course with one video lesson and one enrolled user, end to end. The v1.8 diff bumps dplayer, which strongly implies lesson playback is a first-class part of the package — so proving the video path renders and records progress is the highest-value smoke test. Do that before touching your real domain.

Implementation Patterns

Gate everything through enrollment. Treat the package's course/lesson routes as untrusted until you've read the middleware stack. The standard pattern is a policy or a small middleware that resolves Course from the route and checks an enrollments record for auth()->user():

Route::middleware(['auth', 'enrolled'])->group(function () {
    Route::get('/courses/{course}/lessons/{lesson}', [LessonController::class, 'show']);
});

Wrap authoring in its own policy. Instructor-facing CRUD (create course, add lesson, reorder) should sit behind a CoursePolicy with create/update/delete methods, not behind a role string check scattered across controllers. If the package ships its own controllers, override the model via the config's model map rather than forking.

Keep progress writes idempotent. Video progress is the classic source of duplicate rows — the player fires timeupdate/completion repeatedly. Use updateOrCreate keyed on (user_id, lesson_id), or a dedicated markComplete() action, and debounce on the client:

axios.post(`/api/lessons/${lessonId}/progress`, { position: seconds })
    .catch(() => {/* swallow — never block playback */});

Serve video through signed URLs, not public disk paths. If lessons store a path on the public disk, swap to Storage::disk('local')->temporaryUrl(...) (or a streaming controller) so unenrolled users can't guess URLs. This matters more than anything else in the package for a paid-course use case.

Push side effects into events. Enrollment created, lesson completed, course finished — model these as events with queued listeners for emails, certificate generation, and external LMS/webhook sync. That keeps the package's write path thin and makes your customizations survive upgrades.

Headless usage. If you're building a SPA or mobile client, expose the package models through your own API resources rather than serializing them directly — you control the shape, and the package's toArray() won't leak internal columns when it changes.

Gotchas and Tips

  • v1.8 specifically: both changes are frontend dependency bumps (axios, dplayer) plus a maintainer PR. There is no feature or breaking-change signal in the notes. Before upgrading, diff PR #30 and PR #28 — a major-version bump of either library is the realistic breakage vector, and the release notes won't tell you.
  • Re-publish and rebuild after upgrading. If assets are published to public/vendor/lms, a dplayer bump means the shipped JS changed. Run vendor:publish --force --tag=lms-assets (check the tag) and clear the view/asset cache; otherwise you're serving the old player against new backend expectations or vice versa. Also wipe node_modules if you compile the package's JS yourself — axios major bumps have historically changed default withCredentials, interceptor ordering, and CSRF header handling, which surfaces as mysterious 419s.
  • Publishing twice creates migration collisions. vendor:publish defaults to not overwriting, so after an upgrade you can end up with stale migrations that migrate then re-runs under new filenames. Diff the package's database/migrations against yours before publishing again.
  • Authorization is usually the gap, not the feature. Packages in this space ship working CRUD with thin or configurable middleware. Audit every package route for auth and enrollment checks; a missing can: on a lesson route is a content-leak bug, not a UX bug.
  • Watch for N+1 on course listings. Course::withCount('lessons') and eager-loading enrollments for the index page is the difference between 3 queries and 300. Enable Model::preventLazyLoading() in local dev to catch it.
  • Extension points, in order of safety: config file → published views → custom model subclass registered in config → service binding override → forking. Stay as far left as you can; a fork means every future release is a manual merge.
  • Debugging: the package's internals are rarely well-logged. Add a temporary DB::listen() or a Log::info in the enrollment path rather than guessing; php artisan tinker against the package models is faster than reading source for behavior questions.
  • Pin the version. Given the changelog is auto-generated with no migration or breaking-change notes, use "^1.8" with a committed composer.lock and read the compare diff before any minor bump that touches JS dependencies.
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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo