<?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function($t) { $t->increments('id'); $t->string('name'); $t->string('email'); $t->string('password'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('users'); } }

Now create user_referrals table

php artisan migrate:make create_user_referrals_table

It only contains id,user_id,referral_id,email and tries . user_id is the id of the referral and referral_id is the person who referred him , we also have email column because user_id cannot always be greater than 0 . Think when you referred a user for example developers@kodeinfo.com you will use the email id but if user is not registered in our system it wont have user_id so user_id will be 0 and email will be developers@kodeinfo.com and goes into pending referrals . Tries is the number of times you sent referral invitation to the user we wont be covering tries or referring a user , we assume we have all data in our tables to work .

<?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateUserReferralsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('user_referrals', function($t) { $t->increments('id'); $t->integer('referral_id'); $t->integer('user_id'); $t->string('email'); $t->integer('tries'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('user_referrals'); } }

Now run migration

php artisan migrate

If you get any errors check your config/database.php and make sure database exists and username , password are correct .

Now lets seed some users into our tables and auto refer some users .

<?php class DatabaseSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { Eloquent::unguard(); $this->addUsers(); } private function addUsers() { DB::table('users')->insert([ 'name' => 'Dave', 'email' => 'dave@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('Dave ....'); DB::table('users')->insert([ 'name' => 'Bob', 'email' => 'bob@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('Bob ....'); DB::table('users')->insert([ 'name' => 'Jim', 'email' => 'jim@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('Jim ....'); DB::table('users')->insert([ 'name' => 'Joe', 'email' => 'joe@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('Joe ....'); DB::table('users')->insert([ 'name' => 'Jack', 'email' => 'jack@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('Jack ....'); DB::table('users')->insert([ 'name' => 'Mitch', 'email' => 'mitch@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('Mitch ....'); DB::table('users')->insert([ 'name' => 'David', 'email' => 'david@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('David ....'); DB::table('users')->insert([ 'name' => 'Paul', 'email' => 'paul@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('Paul ....'); DB::table('users')->insert([ 'name' => 'Rauf', 'email' => 'rauf@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('Rauf ....'); DB::table('users')->insert([ 'name' => 'Salim', 'email' => 'salim@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('Salim ....'); DB::table('users')->insert([ 'name' => 'Imran', 'email' => 'imran@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('Imran ....'); DB::table('users')->insert([ 'name' => 'Irfan', 'email' => 'irfan@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('Irfan ....'); DB::table('users')->insert([ 'name' => 'Vincent', 'email' => 'vincent@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('Vincent ....'); DB::table('users')->insert([ 'name' => 'Kenny', 'email' => 'kenny@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('Kenny ....'); DB::table('users')->insert([ 'name' => 'Karen', 'email' => 'karen@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('Karen ....'); DB::table('users')->insert([ 'name' => 'Cris', 'email' => 'cris@gmail.com', 'password' => Hash::make('311311') ]); $this->command->info('Cris ....'); $this->command->info('Seeding referrals ....'); DB::table('user_referrals')->insert([ 'referral_id' => 1, 'user_id' => 2, 'email' => '', 'tries' => 0 ]); DB::table('user_referrals')->insert([ 'referral_id' => 1, 'user_id' => 3, 'email' => '', 'tries' => 0 ]); DB::table('user_referrals')->insert([ 'referral_id' => 2, 'user_id' => 4, 'email' => '', 'tries' => 0 ]); DB::table('user_referrals')->insert([ 'referral_id' => 2, 'user_id' => 5, 'email' => '', 'tries' => 0 ]); DB::table('user_referrals')->insert([ 'referral_id' => 3, 'user_id' => 6, 'email' => '', 'tries' => 0 ]); DB::table('user_referrals')->insert([ 'referral_id' => 3, 'user_id' => 7, 'email' => '', 'tries' => 0 ]); DB::table('user_referrals')->insert([ 'referral_id' => 4, 'user_id' => 8, 'email' => '', 'tries' => 0 ]); DB::table('user_referrals')->insert([ 'referral_id' => 4, 'user_id' => 9, 'email' => '', 'tries' => 0 ]); DB::table('user_referrals')->insert([ 'referral_id' => 5, 'user_id' => 10, 'email' => '', 'tries' => 0 ]); DB::table('user_referrals')->insert([ 'referral_id' => 5, 'user_id' => 11, 'email' => '', 'tries' => 0 ]); $this->command->info('Done ....'); } }

We are done with migrations and seeding lets start creating our function which creates array and html which can be used to draw jorgchart .

Creating JOrgChart Class

jQuery OrgChart is a plugin that allows you to render structures with nested elements in a easy-to-read tree structure. To build the tree all you need is to make a single line call to the plugin and supply the HTML element Id for a nested unordered list element that is representative of the data you’d like to display. If drag-and-drop is enabled you’ll be able to reorder the tree which will also change the underlying list structure.

Create a new folder inside the app and name it KodeInfo , create a new class name it JOrgChart .We will create one method which will take user_id and returns html_string and array of constructed referral tree . Our class is below

<?php namespace KodeInfo; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Input; class JOrgChart { public $chain = []; public $tree_string = ""; public function getChart($referral_id) { $users = DB::table('user_referrals')->where('referral_id', $referral_id)->where('user_id', '>', 0)->lists('user_id'); $this->chain[$referral_id] = $users; //[1]=>[2 ,3] $this->recursiveTree($users, $this->chain[$referral_id]); return ['tree_array' => $this->chain, 'tree_string' => $this->tree_string]; } public function recursiveTree($referral_ids, &$arr) { $this->tree_string .= "<ul>"; // [1]=>[2,3] $arr is at [1] for ($i = 0; $i < sizeof($referral_ids); $i++) { //index 2 $referrals = DB::table('user_referrals')->where('referral_id', $referral_ids[$i])->where('user_id', '>', 0)->lists('user_id'); //index 2 users 4,5 //by reference on 2 nd array $find_user = DB::table('users')->where('id', $arr[$i])->first(); $this->tree_string .= "<li title='This is tooltip for user $find_user->name'><label>$find_user->name</label>"; unset($arr[$i]); $arr[$referral_ids[$i]] = $referrals; if (sizeof($referrals) > 0) { //[2]=>[4,5] reference [2]=> $this->recursiveTree($referrals, $arr[$referral_ids[$i]]); } $this->tree_string .= "</li>"; } $this->tree_string .= "</ul>"; } }

In the above code, we are passing referral_id to a getChart method which will check if this user have referred any users . If he has reffered users then we will pass ids to the recursiveTree method .

public function getChart($referral_id) { $users = DB::table('user_referrals')->where('referral_id', $referral_id)->where('user_id', '>', 0)->lists('user_id'); $this->chain[$referral_id] = $users; //[1]=>[2 ,3] $this->recursiveTree($users, $this->chain[$referral_id]); return ['tree_array' => $this->chain, 'tree_string' => $this->tree_string]; }

Now recursiveTree will track each id to the deepest path and come back for other id . So recursiveTree calls itself recursively to build child nodes .

Creating View

Lets create our views to display what we have created till now . We just need to display tree variable since we already created our structure . Create new view as index.blade.php

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Referral Tree</title> <style type="text/css"> .jOrgChart { margin: 10px; padding: 20px; } .jOrgChart .node { font-size: 14px; background-color: #35363B; border-radius: 8px; border: 5px solid white; color: #F38630; -moz-border-radius: 8px; } .node label { font-family: tahoma; font-size: 14px; line-height: 11px; padding-top: 30px; } </style> </head> <body> <div class="container"> <ul id="org" style="display:none"> <li> <label>Tree</label> {{$tree}} </li> </ul> <div id="chart" style="height:500px;padding-bottom: 80px;" class="orgChart"> <div class="zoom"> <span class="zoom_control">+</span> <div id="zoom_slider"></div> <span class="zoom_control">-</span> </div> </div> </div> {{HTML::style("//code.jquery.com/ui/1.11.0/themes/smoothness/jquery-ui.css")}} {{HTML::style("//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css")}} {{HTML::script("//code.jquery.com/jquery-1.11.0.min.js")}} {{HTML::script("//code.jquery.com/jquery-migrate-1.2.1.min.js")}} {{HTML::script("//code.jquery.com/ui/1.11.0/jquery-ui.js")}} {{HTML::script("//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js")}} {{HTML::script("/assets/jorg-charts/jquery.jOrgChart.js")}} {{HTML::style("/assets/jorg-charts/tree.css")}} {{HTML::script("/assets/jorg-charts/tree.js")}} {{HTML::script("/assets/jquery-kinetic/jquery.kinetic.js")}} <script type="text/javascript"> $(document).ready(function () { $("#org").jOrgChart({ chartElement: '#chart', dragAndDrop: false, slider: true }); $('#chart .cgsnode').tooltip(); $('#chart').kinetic(); }); </script> </body> </html>

In above code, we are also using slider from jquery ui so jquery ui is required . we are using kinetic jquery plugin for dragging our view to scroll . Our tree.js have all functions which are required to display the tree and click handlers . It takes the title attribute and set it as data-original-title for showing tooltip .

Lets create a route to our HomeController

Route::get('/','HomeController@index');

I have downloaded and extracted my jorgchart files into /public/assets/jorg-charts and jquery kinetic plugin in /public/assets/jquery-kinetic

At last autoload the KodeInfo directory so our new class will work .