KodeInfo | Learning resources for web and mobile development

Referral Tree using JOrgChart and Laravel / PHP

October 22nd, 2014 13:27:51 in Schema Builder , Templates , Views by Imran Iqbal Comments(0) - Views(9972)
Tags : jorgchart, laravel jorgchart, php jorgchart, referral tree, laravel tutorials, php laravel

Hi ,
Today we will learn how to create referral tree using jOrgChart and php . I will be using laravel but it can easily be integrated into any php application . Do a fresh install of laravel and follow below steps
1. Migrations and Seeding
2. Creating JOrgChart Class
3. Creating View 
4. Javascript to Handle Tooltip and Kinetic 

 

Migrations and Seeding

Before we jump in and start creating our class we need our users  and user_referrals table with some dummy data to work . So lets create two migrations one for users and other for user_referrals .

 

php artisan migrate:make create_users_table

Lets keep it simple create only id,name,email and password as below

<?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 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 , 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 getChart method which will check if this user have referred any users . If he has reffered users then we will pass ids to 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 .

Thanks

KodeInfo

 

Author

  • Imran Iqbal
    Imran Iqbal

    Imran is a web developer and consultant from India. He is the founder of KodeInfo, the PHP and Laravel Community . In the meantime he follows other projects, works as a freelance backend consultant for PHP applications and studies IT Engineering . He loves to learn new things, not only about PHP or development but everything.

Related

WHY USE A FRAMEWORK OVER PLAIN PHP

WHY USE A FRAMEWORK OVER PLAIN PHP
read more

GETTING STARTED WITH LARAVEL

GETTING STARTED WITH LARAVEL
read more

UNDERSTANDING LARAVEL STRUCTURE

UNDERSTANDING LARAVEL STRUCTURE
read more

UNDERSTANDING LARAVEL ROUTES

UNDERSTANDING LARAVEL ROUTES
read more

comments powered by Disqus