post-image

Xây dựng hệ thống referral trong Laravel

Tổng quan

Hiện nay, thương mại điện tử đang đạt đến đỉnh cao, rất nhiều các chương trình được đưa ra nhằm tăng doanh số bán hàng, quảng bá sản phẩm mạnh mẽ hơn. Một trong những cách thức đó là các chương trình giới thiệu bán hàng (referral system), nó giống như mô hình truyền thống trong việc mở rộng các đại lý phân phối sản phẩm, tuy nhiên có một điểm khác biệt là các đại lý truyền thống cần có sản phẩm để bán thì với chương trình này, đại lý chỉ việc giới thiệu các sản phẩm, dựa trên uy tín của mình, đại lý có thể giới thiệu được nhiều sản phẩm và có thu nhập tốt.

Hệ thống referral là cần thiết?

Các chương trình giới thiệu bán hàng đã tận dụng được lợi thế về quảng bá trên Internet giúp bạn nhanh chóng mở rộng được đại lý bán hàng, tuy nhiên bạn cũng phải thường xuyên tạo ra các chương trình chia sẻ lợi nhuận hấp dẫn, thiết kế các mẫu quảng bá thu hút người xem (hoặc do các đại lý thiết kế) và quan trọng hơn nữa là thường xuyên tạo ra các chương trình chi ân nhằm giữ chân khách hàng lâu dài. Như vậy, có thể thấy Referral là hệ thống quan trọng đối với một website bán hàng, với các website khác áp dụng hệ thống referral cũng là cách tốt để có được lượng traffict lớn ngoài các thành viên thường xuyên.

Xây dựng hệ thống referral trong Laravel

Trong mô hình trên, bạn có thể thấy tất cả các đối tượng tham gia đều được hưởng lợi:

  • Người giới thiệu (hay còn gọi là đại lý): sẽ nhận được hoa hồng khi giao dịch thành công.
  • Người được mời (người mua): nhận được các chương trình giảm giá, chương trình chi ân khách hàng từ hệ thống. Các hệ thống bán hàng có thể giảm giá tốt hơn với các khách hàng tiềm năng này.
  • Nhà phân phối (có hệ thống giới thiệu bán hàng – referral system): tăng doanh số bán hàng, tiếp cận được nhiều khách hàng tiềm năng.

Xây dựng hệ thống giới thiệu bán hàng – referral system trong ứng dụng Laravel

Bước 1: Tạo các bảng liên quan trong CSDL

Chúng ta sẽ tạo ra hai bảng referral_programs và referral_links:

c:\xampp\htdocs\laravel-test>php artisan make:migration create_referral_programs_table --create=referral_programs Created Migration: 2017_04_24_075438_create_referral_programs_table c:\xampp\htdocs\laravel-test>php artisan make:migration create_referral_links_table --create=referral_links Created Migration: 2017_04_24_075503_create_referral_links_table c:\xampp\htdocs\laravel-test>php artisan make:migration create_referral_relationships_table --create=referral_relationships Created Migration: 2017_04_24_081042_create_referral_relationships_table

Thêm nội dung tạo các bảng liên quan, với file 2017_04_24_075438_create_referral_programs_table:

<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateReferralProgramsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('referral_programs', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('uri'); $table->integer('lifetime_minutes')->default(7 * 24 * 60); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('referral_programs'); } }
Code language: HTML, XML (xml)

Với file 2017_04_24_075503_create_referral_links_table:

<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateReferralLinksTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('referral_links', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id')->unsigned(); $table->integer('referral_program_id')->unsigned(); $table->string('code', 36)->index(); $table->unique(['referral_program_id', 'user_id']); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('referral_links'); } }
Code language: HTML, XML (xml)

Thêm nội dung tạo referral_relationships:

<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateReferralRelationshipsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('referral_relationships', function (Blueprint $table) { $table->increments('id'); $table->integer('referral_link_id'); $table->integer('user_id'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('referral_relationships'); } }
Code language: HTML, XML (xml)

Tiếp theo thực hiện tạo hai bảng này bằng lệnh php artisan migrate

c:\xampp\htdocs\laravel-test>php artisan migrate Migrated: 2017_04_24_075438_create_referral_programs_table Migrated: 2017_04_24_075503_create_referral_links_table Migrated: 2017_04_24_081042_create_referral_relationships_table

Bước 2: Tạo Eloquent Model

Sử dụng câu lệnh artisan make:model để tạo ba model là ReferralProgram, ReferralLink và ReferralRelationship

c:\xampp\htdocs\laravel-test>php artisan make:model ReferralProgram Model created successfully. c:\xampp\htdocs\laravel-test>php artisan make:model ReferralLink Model created successfully. c:\xampp\htdocs\laravel-test>php artisan make:model ReferralRelationship Model created successfully.
Code language: CSS (css)

Trong project này chúng ta sẽ sử dụng package ramsey/uuid là một thư viện làm việc với Universally Unique Identifiers (UUID) tương thích với tiêu chuẩn RFC 4122 phiên bản 1, 3, 4 và 5. Thực hiện cài đặt vào dự án bằng lệnh composer.

c:\xampp\htdocs\laravel-test>composer require ramsey/uuid Using version ^3.6 for ramsey/uuid ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 0 installs, 1 update, 0 removals - Updating ramsey/uuid (3.6.0 => 3.6.1): Loading from cache Writing lock file Generating autoload files > Illuminate\Foundation\ComposerScripts::postUpdate > php artisan optimize Generating optimized class loader The compiled services file has been removed.
Code language: JavaScript (javascript)

Ngoài ra chúng ta cần cài đặt thêm gói moontoast/math được sử dụng trong các thuật toán của ramsey/uuid:

c:\xampp\htdocs\laravel-test>composer require moontoast/math Using version ^1.1 for moontoast/math ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 1 install, 0 updates, 0 removals - Installing moontoast/math (1.1.2): Downloading (100%) Writing lock file Generating autoload files > Illuminate\Foundation\ComposerScripts::postUpdate > php artisan optimize Generating optimized class loader The compiled services file has been removed.
Code language: JavaScript (javascript)

Nội dung các model như sau, ReferralProgram:

<?php namespace App; use Illuminate\Database\Eloquent\Model; class ReferralProgram extends Model { protected $fillable = ['name', 'uri', 'lifetime_minutes']; }
Code language: HTML, XML (xml)

ReferralLink:

<?php namespace App; use Illuminate\Database\Eloquent\Model; use Ramsey\Uuid\Uuid; class ReferralLink extends Model { protected $fillable = ['user_id', 'referral_program_id']; protected static function boot() { static::creating(function (ReferralLink $model) { $model->generateCode(); }); } private function generateCode() { $this->code = (string)Uuid::uuid1(); } public static function getReferral($user, $program) { return static::firstOrCreate([ 'user_id' => $user->id, 'referral_program_id' => $program->id ]); } public function getLinkAttribute() { return url($this->program->uri) . '?ref=' . $this->code; } public function user() { return $this->belongsTo(User::class); } public function program() { // TODO: Check if second argument is requried return $this->belongsTo(ReferralProgram::class, 'referral_program_id'); } public function relationships() { return $this->hasMany(ReferralRelationship::class); } }
Code language: HTML, XML (xml)

ReferralRelationship:

<?php namespace App; use Illuminate\Database\Eloquent\Model; class ReferralRelationship extends Model { protected $fillable = ['referral_link_id', 'user_id']; }
Code language: HTML, XML (xml)

Tiếp theo chúng ta cần giám sát các đường link có tham số ref và lưu chúng vào cookie, như vậy mỗi khi có một hành động nào đó của người dùng chúng ta có thể biết và tặng quà cho cả hai bên tham gia. Để thực hiện được việc này chúng ta tạo ra một middleware.

c:\xampp\htdocs\laravel-test>php artisan make:middleware StoreReferralCode Middleware created successfully.
Code language: CSS (css)

và thay đổi nội dung app\Middlewares\StoreReferralCode.php như sau:

<?php namespace App\Http\Middleware; use Closure; use App\ReferralLink; class StoreReferralCode { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { $response = $next($request); if ($request->has('ref')){ $referral = ReferralLink::whereCode($request->get('ref'))->first(); $response->cookie('ref', $referral->id, $referral->lifetime_minutes); } return $response; } }
Code language: HTML, XML (xml)

Sau đó đăng ký middleware này như một global middleware bằng cách thêm vào trong file app\Http\Kernel.php:

'web' => [ ... \App\Http\Middleware\StoreReferralCode::class, ]
Code language: PHP (php)

Phương thức handle() của middleware StoreReferralCode sẽ thực hiện kiểm tra tất cả các request nếu có tham số ref sẽ tìm kiếm

Bước 4: Tạo Event và Listener quản lý các hành động người dùng

Khi hành động như mong muốn được người dùng thực hiện (ở đây là đăng ký tài khoản mới), chúng ta thực hiện tạo ra một event và dùng listener để bắt sự kiện đó, trong listener sẽ thực hiện tặng thưởng cho người dùng. Thêm cấu hình vào EventServiceProvider.php trong thư mục app\Providers:

protected $listen = [ ... 'App\Events\UserReferred' => [ 'App\Listeners\RewardUser', ], ];
Code language: PHP (php)

Sau đó sử dụng lệnh artisan event:generate để tự động tạo ra Event và Listener (Xem thêm Quản lý sự kiện với Laravel Event để hiểu hơn về câu lệnh này):

c:\xampp\htdocs\laravel-test>php artisan event:generate Events and listeners generated successfully!
Code language: CSS (css)

Thay đổi nội dung của Event app\Events\UserReferred.php:

<?php namespace App\Events; use Illuminate\Broadcasting\Channel; use Illuminate\Queue\SerializesModels; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; class UserReferred { use Dispatchable, InteractsWithSockets, SerializesModels; public $referralId; public $user; /** * Create a new event instance. * * @return void */ public function __construct($referralId, $user) { $this->referralId = $referralId; $this->user = $user; } /** * Get the channels the event should broadcast on. * * @return Channel|array */ public function broadcastOn() { return new PrivateChannel('channel-name'); } }
Code language: HTML, XML (xml)

Thêm nội dung của app\Listener\RewardUser.php:

<?php namespace App\Listeners; use App\Events\UserReferred; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; class RewardUser { /** * Create the event listener. * * @return void */ public function __construct() { // } /** * Handle the event. * * @param UserReferred $event * @return void */ public function handle(UserReferred $event) { $referral = \App\ReferralLink::find($event->referralId); if (!is_null($referral)) { \App\ReferralRelationship::create(['referral_link_id' => $referral->id, 'user_id' => $event->user->id]); // Tặng thưởng cho cả người share link và người sử dụng link if ($referral->program->name === 'Bonus Credits') { // Người chia sẻ link $provider = $referral->user; $provider->addCredits(15); // Người sử dụng link $user = $event->user; $user->addCredits(20); } } } }
Code language: HTML, XML (xml)

Ok, tiếp theo chúng ta sẽ tạo ra một event app\Events\UserReferred.php khi người dùng đăng ký bằng cách can thiệp vào phương thức create() của RegisterController.php nằm trong app\Http\Controllers\Auth:

/** * Create a new user instance after a valid registration. * * @param array $data * @return User */ protected function create(array $data) { $user = User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => bcrypt($data['password']) ]); event(new \App\Events\UserReferred(request()->cookie('ref'), $user)); return $user; }
Code language: PHP (php)

Bước 5: Thêm view và route cho referral system

Thêm route vào routes/web.php:

Route::get('/referral', function(){ return view('fontend.referral'); });
Code language: PHP (php)

Tạo view referral.blade.php trong resources/views/fontend:

@extends('layouts.default') @section('title', 'Referral system - Allaravel.com') @section('content') @forelse(auth()->user()->getReferrals() as $referral) <h4> Chươngng trìnhh: {{ $referral->program->name }} </h4> <code> Referral link: {{ $referral->link }} </code> <p> Số$referral->relationships()->count() }} </p> @empty Khôngg có
Code language: PHP (php)

Thêm menu Referral System vào resources/views/layouts/menu.php:

<!-- Fixed navbar --> <nav class="navbar navbar-default navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/">All Laravel TEnv</a> </div> <div id="navbar" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li class="active"><a href="/">Trang chủ</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Ví dụ <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="/first-blade-example">Ví dụ Blade 1</a></li> <li><a href="/second-blade-example">Ví dụ Blade 2</a></li> <li><a href="{{ URL::to('/referral') }}">Referral System</a></li> </ul> </li> {!! Form::open(array('url' => '/search', 'class' => 'navbar-form navbar-left', 'method' => 'get')) !!} <div class="form-group"> {!! Form::text('keyword', '', array('class' => 'form-control', 'placeholder' => 'Nhập từ khóa...')) !!} </div> {!! Form::submit('Tìm kiếm', array('class' => 'btn btn-default')) !!} {!! Form::close() !!} <li><a href="/contact">Liên hệ</a></li> @if(Session::has('login') && Session::get('login') == true) <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Xin chào {{ Session::get('name') }} <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="/logout">Đăng xuất</a></li> </ul> </li> @endif </ul> </div><!--/.nav-collapse --> </div> </nav>
Code language: HTML, XML (xml)

Kiểm tra kết quả hoạt động hệ thống referral

Trước khi đi vào kiểm tra hoạt động hệ thống referral, chúng ta cùng xem qua luồng hoạt động của nó.

Xây dựng hệ thống referral trong Laravel

Các bước thực hiện kiểm thử cũng sẽ tuân thủ theo hoạt động mô tả ở luồng hoạt động hệ thống ở trên: Đầu tiên, đăng nhập vào hệ thống laravel.dev tại http://laravel.dev/login, sau khi đăng nhập chuyển sang menu Ví dụ->Referral System. Nhưng trước tiên chúng ta cần tạo ra một chương trình giới thiệu bán hàng trước đã do hiện tại bảng referral_programs đang chưa có bản ghi nào. Sử dụng Laravel Tinker để nhập nhanh một bảng ghi (Nếu bạn chưa biết Tinker là gì xem thêm Công cụ debug và kiểm thử trong Laravel):

c:\xampp\htdocs\laravel-test>php artisan tinker Psy Shell v0.8.3 (PHP 5.6.20 ΓÇö::create(['name'=>'register', 'uri' => 'register']); => App\ReferralProgram {#714 name: "register", uri: "register", updated_at: "2017-04-24 08:24:42", created_at: "2017-04-24 08:24:42", id: 1, } >>> exit Exit: Goodbye.
Code language: PHP (php)
Xây dựng hệ thống referral trong Laravel

Như vậy, thành viên này đã có referral link, thành viên này muốn kiếm tiền có thể đưa đường dẫn này vào bất kỳ đâu: – Mạng xã hội Facebook, Google Plus, Twitter, Github…

  • Website: Blog, trang tin tức…
  • Email: Gửi email trong nội dung có đường dẫn này.

Bất kỳ ai khi thực hiện click vào đường dẫn này, hệ thống sẽ ghi xuống máy tính của họ một cookie chứa id bản ghi trong referral_links, cookie này có thời gian hoạt động mặc định là 7 ngày, do trong phần tạo bảng referral_programs chúng ta để là:

$table->integer('lifetime_minutes')->default(7 * 24 * 60);
Code language: PHP (php)

Trong khoảng thời gian này, nếu người dùng trên thực hiện đăng ký tài khoản, referral system sẽ biết do đã cài đặt các Event và Listener. Khi đó tùy thuộc vào chương trình giới thiệu bán hàng chúng ta sẽ xử lý trả thưởng cho cả người chia sẻ link và người dùng link trong phương thức hanlde() của Listener.

/** * Handle the event. * * @param UserReferred $event * @return void */ public function handle(UserReferred $event) { $referral = \App\ReferralLink::find($event->referralId); if (!is_null($referral)) { \App\ReferralRelationship::create(['referral_link_id' => $referral->id, 'user_id' => $event->user->id]); // Tặng thưởng cho cả người share link và người sử dụng link if ($referral->program->name === 'Bonus Credits') { // Người chia sẻ link $provider = $referral->user; $provider->addCredits(15); // Người sử dụng link $user = $event->user; $user->addCredits(20); } } }
Code language: PHP (php)

Để kiểm tra các công đoạn này, chúng ta mở một trình duyệt khác và dán vào đường dẫn referral ở trên (Trong bài viết này, người chia sẻ link dùng Chrome, người dùng link sử dụng Firefox):

Xây dựng hệ thống referral trong Laravel

Khi thực hiện đăng ký xong, quay trở lại với người chia sẻ link chúng ta sẽ thấy số lượng người sử dụng link tăng lên:

Xây dựng hệ thống referral trong Laravel

Ok, như vậy referral system của chúng ta đã hoạt động tốt. Với khung ứng dụng này, chúng ta hoàn toàn có thể thực hiện các hệ thống referral với các sự kiện phức tạp hơn.

Các bạn có thể tham khảo các bài viết hay về Laravel tại đây.


Hãy tham gia nhóm Học lập trình để thảo luận thêm về các vấn đề cùng quan tâm.

Tham khảo: https://topdev.vn/blog/xay-dung-he-thong-referral-trong-laravel/

Leave a Reply

Your email address will not be published. Required fields are marked *