Using invite codes for registrations with the Laravel invite codes package.
Having invite codes for your web application means you can limit who you want to register.
The Laravel Invite Codes package can be installed with
composer require mateusjunges/laravel-invite-codes
Then migrate the invite codes database table with
php artisan migrate
Creating invite codes
The invite codes have several values to them, some are optional.
Firstly is the invite code itself in a string format, there is an expiry date, a max uses amount and restrict usage to a certain email address.
A Laravel CRUD for an admin to manage invite codes is straightforward, here are the create (store) parts
invites/create.blade.php
<form method="post" action="{{route('invites.store')}}"> @csrf <div class="row mb-3"> <div class="col-lg-4 col-md-4 col-12"> <div class="input-group mb-3"> <span class="input-group-text">Code</span> <input type="text" class="form-control" name="code" minlength="3" maxlength="125" value="{{\Illuminate\Support\Str::random(12)}}" required> </div> </div> <div class="col-lg-4 col-md-4 col-12"> <div class="input-group mb-3"> <span class="input-group-text">Max Uses</span> <input type="number" class="form-control" name="uses" min="1" max="99" value="1" step="1" required> </div> </div> <div class="col-lg-4 col-md-4 col-12"> <div class="input-group mb-3"> <span class="input-group-text">Expires</span> <input type="date" class="form-control" name="expires" value=""> </div> </div> </div> <div class="row mb-3"> <div class="col-lg-6 col-md-6 col-12"> <div class="input-group mb-3"> <span class="input-group-text">Valid only for email address</span> <input type="text" class="form-control" name="email" minlength="6" maxlength="125"> </div> </div> </div> <input type="submit" value="Create" class="btn btn-light-success mt-2 px-5"> </form>
The Invites model:
namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Invite extends Model { use HasFactory; protected $table = 'invites'; protected $fillable = ['code', 'max_usages', 'to', 'uses', 'expires_at']; }
Here is the store method in the InvitesController where the invite code and parameters are inserted into the database:
public function store(Request $request) { $request->validate([ 'code' => 'string|required|min:3|max:125', 'uses' => 'integer|required|min:1|max:99', 'expires' => 'date|nullable', 'email' => 'email|nullable|sometimes|min:6|max:125' ]); try { Invite::create([ 'code' => $request->code, 'max_usages' => $request->uses, 'to' => $request->to ?? null, 'expires_at' => $request->expires ?? null ]); } catch (\Illuminate\Database\QueryException $e) { return redirect()->route('invites.create') ->withInput($request->input()) ->with('error', 'Error creating invite code.'); } return redirect()->route('invites.index') ->with('success', 'Invite code created successfully.'); }
When being validated an expires and/or email can be nullable (excluded).
Validating an invite code
Firstly an input is needed for an invite code to be submitted when registering this is edited in at views/auth/register.blade.php
<div class="col-12"> <div class="mb-3"> <label class="form-label">Invite code</label> <input id="invite" type="text" class="form-control @error('invite') is-invalid @enderror" name="invite" value="{{ old('invite') }}" required autocomplete="username" autofocus> @error('invite') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div>
In the RegisterController the validation needs to include the invite code being checked, this is done with redeem()
in the validator method after the validation on name, email and password
try { InviteCodes::withoutEvents()->redeem($data['invite']); } catch (\Exception) { throw ValidationException::withMessages(['invite' => 'Invite code is invalid']); }
This above example catches any exception therefor if the code doesn’t exist, or it’s the wrong email or it has been used too many times it will all throw the same “Invite code is invalid” response.
To have a custom response go here and get the exception type an example being if the code has been used past its maximum amount:
} catch (\Junges\InviteCodes\Exceptions\SoldOutException) { throw ValidationException::withMessages(['invite' => 'Invite code has been used too many times']); }
Lastly if you wanted to clear expired codes from the database there is a handy artisan command
\Illuminate\Support\Facades\Artisan::call('invite-codes:clear');