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

Profiles Laravel Package

liberusoftware/profiles

A Laravel package for managing user profiles, providing a clean, configurable foundation for profile data, relationships, and common profile workflows. It integrates with Eloquent models and is designed to drop into existing applications with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the module.

    composer require liberusoftware/profiles
    

    If Packagist resolution fails (common for single-maintainer Liberu modules), add the GitHub repo as a VCS repository in composer.json and require dev-main — then pin to a commit SHA.

  2. Publish and migrate.

    php artisan vendor:publish --provider="Liberu\Profiles\ProfilesServiceProvider"
    php artisan migrate
    

    Check config/profiles.php before migrating — table names and the user foreign key are usually configurable, and getting them wrong means a rollback and re-migrate.

  3. Read these files first, in this order:

    • src/ProfilesServiceProvider.php — what's registered, what's publishable, whether routes/views/migrations are loaded conditionally.
    • config/profiles.php — table names, model bindings, upload disk, approval toggles.
    • database/migrations/* — the actual schema is the source of truth for what "controlled updates" means here (look for a status/approved_at/reviewed_by column).
    • src/Models/ and src/Http/Controllers/ — the real public API surface.
  4. First use case: attach the package's profile trait (or relation) to App\Models\User, then let a user edit display name, avatar, timezone, and locale through the package's routes. If an approval column exists in the migration, you have the second use case for free: submissions land as pending and an admin approves them.

  5. Smoke test before writing code:

    php artisan route:list --name=profiles
    php artisan migrate:status
    

    If no routes appear, the module isn't auto-discovered — see Gotchas.

Implementation Patterns

Attach via trait, don't subclass. The typical Liberu module ships a HasProfile trait plus a Profile model with a user() belongsTo. Add the trait to User rather than swapping the model, so module-users, module-teams, and auth keep working.

Read preferences through a single accessor. Presentation preferences (theme, locale, timezone, avatar, notification channels) are usually stored as a JSON column or discrete columns. Wrap reads in one helper/service method ($user->preference('timezone', config('app.timezone'))) so you have one place to add caching and one place to change storage later. Never read the raw JSON column in Blade.

Controlled updates as a two-state workflow. The package's core value is gating profile changes. The pattern that scales:

  • User submits → row created with pending status + snapshot of proposed values.
  • Admin/listener approves → copy proposed values onto the canonical profile, stamp approved_by/approved_at.
  • Reject → keep the request row for audit, notify the user.

Drive the transitions through the package's service/action class if one exists; if not, wrap them in your own action class so events fire consistently.

Hear the events, don't poll. Look for ProfileUpdated, ProfileUpdateRequested, or ProfileApproved in src/Events/. Register listeners to fan out to notifications, audit logs, and search indexing. If events are missing, that's your first fork/PR candidate — it's the cleanest extension point.

Pair with policies. Register a ProfilePolicy (update, approve) and let the package's controllers authorize through it. This is how you get "users edit their own, admins edit anyone" without touching vendor code.

Presentation preferences belong at render time. Resolve theme/locale in a middleware or view composer, cache per-user for the request (once() or a request-scoped singleton), and let the frontend read from a single $user->presentation() array. Keeps controllers thin and makes A/B or per-tenant defaults easy later.

Testing. Use RefreshDatabase. If the package ships factories, use them. For approval flows, freeze time and assert the audit columns — this is the part reviewers care about most.

Gotchas and Tips

  • Zero stars, zero dependents, single maintainer. Treat this as a reference implementation, not infrastructure. Pin an exact version/SHA, and be prepared to vendor-fork src/ into your app if you need a fix. Budget a day for reading before you commit to it.
  • Release metadata looks wrong. The stated last release (2026-10-27) is in the future. Verify the tag actually exists (git ls-remote --tags) before trusting composer require to resolve anything stable.
  • Auto-discovery often fails in modular setups. If the module is built for nwidart/laravel-modules or a modules_statuses.json flag, you must enable it there or manually register the provider in bootstrap/providers.php. Symptom: commands succeed, routes 404.
  • Migrations fight your users table. The package may ship its own users migration or assume a specific foreign key (user_id vs users_id, UUID vs bigint). Read the migration before running it on an existing DB; on a fresh install it's fine, on an existing one it can cascade-delete.
  • Mass updates skip events. Profile::where(...)->update([...]) bypasses model events, so approval listeners silently never fire. Use fill()->save() or the package's action class.
  • Approval race conditions. Two admins approving the same request is the classic bug. Wrap transitions in DB::transaction with lockForUpdate(), and make the status update conditional (where('status','pending')) so the second one no-ops.
  • Avatar/upload disk config. If avatars store under a configurable disk, changing FILESYSTEM_DISK after the fact leaves orphaned URLs. Store the path, resolve the URL at render time.
  • Cache invalidation. If you cache preferences, clear on ProfileUpdated — otherwise theme changes appear "saved but not applied" and you'll burn an hour on it.
  • Config quirks. Publish the config once and diff it against the vendor copy on every upgrade; Liberu modules have a habit of adding keys without defaults, which surfaces as null timezones in production.
  • Debugging checklist: php artisan route:list --name=profiles, check storage/logs/laravel.log for provider boot errors, php artisan about to confirm the provider loaded, and DB::listen() around a save to see whether the write is hitting the expected table.
  • Extension points worth using: model binding in config/profiles.php (swap Profile for your own subclass), the published views (override theme without touching src/), and the event/listener pair. Avoid editing vendor files directly — with no release cadence you'll never get clean merges back.
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.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels