Recently, I was tasked with building a referral system as a feature in an e-commerce application I was working on.
I thought about different scenarios it could be done and even considered some laravel packages that could do the work. But I wanted to make it as simple and less complicated as possible, so I opted for building it from scratch.
Thinking about the fact that I was working on a REST API, the first instance I considered was that a user would have a referral code that can be shared and also another user would be able to input the referral code on registration to denote if he/she was invited by another user.
Therefore, a user can be referred by another user and a user can refer many user.
Looking at the relationship between this; we have a One-to-Many
relationship.
So we edit create_user_table
migration file.
$table->string('referral_code')->unique();
$table->unsignedBigInteger('referred_by_id');
$table->foreign('referred_by_id')->references('id')->on('users');
But in some instances, some users might not have a referrer, so we update the table schema to have it as;
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('phone')->unique()->nullable();
$table->string('password');
$table->string('referral_code')->unique();
$table->unsignedBigInteger('referred_by_id')-
>nullable();
$table->foreign('referred_by_id')->references('id')-
>on('users');
$table->rememberToken();
$table->timestamps();
});
So we migrate the database and make the following changes changes to the User model.
protected $fillable = [
'referred_by_id', 'referral_code' 'name', 'email', 'password', 'phone'
];
public function referredBy()
{
return $this->belongsTo(User::class, 'referred_by_id', 'id');
}
public function referrals()
{
return $this->hasMany(User::class, 'referred_by_id', 'id');
}
So on registration of a new user, we update our registration controller: I have mine to be AuthController
;
class AuthController extends Controller {
public function register(Request $request)
{
$validator = Validator::make(
$request->all(),
[
'name' => ['required', 'string', 'max:255'],
'email' => 'required|email|unique:users',
'password' => 'required',
],
$messages = [
'email.unique' => __('Email already associated
with an account')
]
);
if ($validator->fails()) {
return response()->json([
"message" => $validator->messages(),
], 400);
}
$referrer = User::where('referral_code', $request-
>referral_code)->first();
try {
DB::beginTransaction();
$user = new User();
$user->username = $request->username;
$user->email = $request->email;
$user->phone = $phone;
$user->password = Hash::make($request->password);
$user->referral_code = "RF_" . \Str::random(4);
$user->referred_by_id => $referrer ? $referrer->id
: null,
$user->save();
DB::commit();
if ($user->referrer !== null) {
//perform any logic to gift the referrer or update
the referrer wallet
}
//generate tokens
return $this->authObject($user);
} catch (\Exception$error) {
logger("General error", [$error]);
DB::rollback();
return response()->json([
"message" => $error->getMessage(),
], 500);
}
}
private function authObject($user)
{
$user = User::find($user->id);
$token = $user->createToken('new_token')-
>plainTextToken;
return response()->json([
"token" => $token,
"type" => "Bearer",
"message" => __("User Registered successful 😃"),
]);
}
}
In the above method; we validate the request and create a new user, with an autogenerated referral code of theirs and also update the user with the referrer id if there's any and you can also create any logic to gift the referrer or update their wallet if there is any 😃.
Top comments (1)
I was looking for this system from last many days. Finally I have found something which is working. I was able to integrate it within 30 minutes. Great. Thanks a lot again.