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

Laravel Registrar Laravel Package

genealabs/laravel-registrar

GeneaLabs Laravel Registrar offers a fluent, convention-driven API for registering service container bindings, aliases, and providers in Laravel, reducing boilerplate in service providers and keeping application wiring organized, reusable, and easy to maintain across projects.

View on GitHub
Deep Wiki
Context7

Getting Started

First, resolve what the package actually does — it is not a trivial step here. Three sources disagree: the repository metadata says "user account activation via email confirmation," the packaged description.md describes a fluent service-container registry (register() / resolve() for named implementations), and the only changelog entry (0.1.6) is a "double-save" data-integrity fix. Clone the repo and read the service provider before you write a line of application code. If your goal is container binding ergonomics, the native ServiceProvider API ($this->app->singleton(), bind(), contextual binding) already covers it and this dependency adds nothing but risk. If your goal is email-confirmed signup, continue below.

Minimal install path for a Laravel 5.x-era app:

# 1. Read the constraint block first — do not assume modern framework support
composer show genealabs/laravel-registrar --all

# 2. Pin exactly; there is no maintainer to ship a 0.1.7
composer require genealabs/laravel-registrar:0.1.6

# 3. Publish and migrate
php artisan vendor:publish --provider="GeneaLabs\LaravelRegistrar\LaravelRegistrarServiceProvider"
php artisan migrate --pretend   # inspect before running for real
php artisan migrate

Then apply the package's trait (or extend its base user model) to App\User, point it at the activation column, and configure a mail driver.

Where to look first, in this order — with no real documentation, this five-file read is your entire mental model:

  1. Service provider — what it binds, what it publishes, whether it auto-loads routes.
  2. Published config — table name, token lifetime, redirect targets, notification class.
  3. Migration — which columns it adds to users and what shape it assumes.
  4. Notification/mailable — subject line, view used, URL generation.
  5. Activation controller — the actual state transition and its failure modes.

First use case: the happy path, driven by a feature test, not by clicking. Write it before anything else:

public function test_registration_sends_activation_and_activates_on_click()
{
    Notification::fake();

    $this->post('/register', [
        'name' => 'A', 'email' => '[email protected]',
        'password' => 'secret123', 'password_confirmation' => 'secret123',
    ]);

    $user = User::where('email', '[email protected]')->firstOrFail();
    $this->assertNull($user->activated_at);

    Notification::assertSentTo($user, ActivationNotification::class);

    $this->get($this->activationUrlFor($user));
    $this->assertNotNull($user->fresh()->activated_at);
}

That test is your regression guard for every subsequent change, and it doubles as documentation of a flow the package itself does not document.

Implementation Patterns

Wrap the package; never let it own your routes or controllers. Route your own endpoints and call the package's registrar/action inside them. You keep validation, flash messages, redirects, and audit logging — and you avoid coupling route names to a frozen dependency.

// routes/web.php — your routes, your middleware
Route::post('/register', [RegisterController::class, 'store']);
Route::get('/activate/{token}', [ActivationController::class, 'activate'])
    ->name('activate');

// app/Http/Controllers/ActivationController.php
public function activate(string $token)
{
    $result = $this->registrar->activate($token); // package call, one place

    return match ($result) {
        'activated' => redirect()->route('login')->with('status', 'Account activated.'),
        'already'   => redirect()->route('login')->with('status', 'Already active.'),
        default     => redirect()->route('login')->withErrors('Invalid or expired link.'),
    };
}

Gate authentication on the activation column. A confirmed email is worthless if unactivated users can still log in. Add a check in attemptLogin or a middleware:

protected function attemptLogin(Request $request)
{
    $user = User::where('email', $request->email)->first();

    if ($user && is_null($user->activated_at)) {
        throw ValidationException::withMessages([
            'email' => 'Please confirm your email before signing in.',
        ]);
    }

    return parent::attemptLogin($request);
}

Make activation idempotent. Users double-click; corporate mail scanners prefetch links. The second click must return a friendly "already active" redirect, not a 500 or an "invalid token" error.

Own your token handling if the package does not. Generate random bytes, store a hash, store an expiry, compare with hash_equals. If the package stores raw tokens, add a migration. Expiry should be 24–48h, and there must be a resend endpoint behind a rate limiter.

Replace the notification rather than fight it. If the package's mailable is too rigid, bind your own notification class through the published config. Keep activation-URL generation in exactly one place so a domain change doesn't silently break every outstanding link.

Emit a domain event from your controller, not from the package's internals:

// after successful activation
event(new UserActivated($user));

// app/Listeners/SendWelcomeEmail.php — queued, idempotent
public function handle(UserActivated $event): void
{
    if ($event->user->welcome_sent_at) {
        return;
    }
    // ...
}

Post-activation side effects (welcome email, seed default records, analytics) hang off that listener. It is testable, it is yours, and it survives the day you rip the package out.

Testing patterns that pay for themselves:

  • Notification::fake() plus assert-sent-to-the-right-user; Mail::fake() if it uses a mailable.
  • Factory states: ->unactivated() and ->activated().
  • One test per edge: valid token, expired token, reused token, unknown token, resend throttle.
  • MAIL_MAILER=array and QUEUE_CONNECTION=sync in phpunit.xml so nothing escapes and nothing stalls.

Plan the exit while you are integrating. Put every package touchpoint behind one small class (ActivationService) with your own interface. When you replace it with MustVerifyEmail + signed URLs + the verified middleware, you change one file.

Gotchas and Tips

  • Archived means archived. Last release August 2018, 9 stars, 0 dependents. No security channel, no Laravel 8/9/10/11 compatibility, no maintainer response. Pin 0.1.6 exactly and put a replacement ticket on the board the same day you install it.
  • The description in the distribution metadata is wrong. If anyone reads the bundled blurb and expects a service-container helper, they will be confused by an activation flow. Write the real behavior into your team docs.
  • 0.1.6 is a data-integrity patch, not cosmetics. Before upgrading anywhere 0.1.5-or-earlier ran, audit for duplicate user rows, duplicate activation/token rows, and duplicate activation emails. Set a timestamp cutoff before deploying — afterwards, new writes are clean and old ones are indistinguishable.
  • Side effects probably fired twice too. The double-save fix does not repair historical double-fires. Grep your listeners and check outbound mail/webhook logs for duplicated sends in the affected window.
  • Migration collisions. The published migration assumes a users table with a specific shape. If your model is App\Models\User rather than App\User, or your table is named differently, edit the migration and any hardcoded model references. Always migrate --pretend first.
  • Route and guard conflicts. If you already call Auth::routes(), names or middleware will collide. Run php artisan route:list right after install and diff for duplicates.
  • Config and view caching. "The email still looks old" is almost always php artisan config:clear && php artisan view:clear. Do it as part of every deploy that touches published assets.
  • A stalled queue looks identical to a broken registration. If the activation notification is queued, verify the worker during your first smoke test. In tests, force sync.
  • The three places activation flows actually break in production: timing-safe token comparison, expiry messaging, and resend throttling. Handle all three yourself if the package doesn't.
  • Extension points, in order of preference: published config → published views → notification class override → model events → forking. Never edit vendor/. An archived package will never accept your PR, so a fork is a permanent commitment — decide that deliberately, not accidentally.
  • Debugging checklist for any "activation doesn't work" report: MAIL_* env and driver → queue worker running → config cache cleared → route registered and not shadowed → trait applied to the model → activation column present and fillable → token not already expired. That sequence resolves the large majority of reports.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console