Create charts in Laravel with eloquent and Larapex Charts

Ariel Mejia - Jan 16 '20 - - Dev Community

Alt Text

What is Larapex?

It is a Laravel package that provides a wrapper to create apexcharts with only PHP.

What we are going to build?

An eloquent example to create charts from eloquent queries

Lets start

First create a project

In valet

laravel new yourproject 
Enter fullscreen mode Exit fullscreen mode

With composer

composer create-project --prefer-dist laravel/laravel yourproject  
Enter fullscreen mode Exit fullscreen mode

Then add the LarapexChart Package

Go to your app directory and in your console/terminal/cmd/bash type:

composer require arielmejiadev/larapex-charts 
Enter fullscreen mode Exit fullscreen mode

About the project.

It will simulate a TODO app with users that creates TODOS, this tutorial will show all commands and code in every file, so just follow the steps.

I will create a TODO model and assign TODOS to users (with default User model from a fresh Laravel installation).

To create a model with migrations, factories and seeders you can use the flag "a" with the make model artisan command:

php artisan make:model Todo -a 
Enter fullscreen mode Exit fullscreen mode

The TODO Model file content will look like this:

namespace App;

use Illuminate\Database\Eloquent\Model;

class Todo extends Model
{
    protected $fillable = [
        'title', 'state', 'user_id'
    ];

    protected $casts = [
        'status' => 'boolean',
    ];

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

Enter fullscreen mode Exit fullscreen mode

The User model file content:


namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function todos()
    {
        return $this->hasMany(Todo::class);
    }
} 
Enter fullscreen mode Exit fullscreen mode

The TODO migration file content:


use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateTodosTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('todos', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('title');
            $table->boolean('status')->default(false);
            $table->unsignedBigInteger('user_id');
            $table->foreign('user_id')->references('id')->on('users');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('todos');
    }
}

Enter fullscreen mode Exit fullscreen mode

TODO Factory content:

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Todo;
use App\User;
use Faker\Generator as Faker;

$factory->define(Todo::class, function (Faker $faker) {
    return [
        'title'     => $faker->title,
        'status'    => $faker->boolean,
        'user_id'   => factory(User::class),
    ];
});
Enter fullscreen mode Exit fullscreen mode

The TODO Seeder content:


use App\User;
use App\Todo;
use Illuminate\Database\Seeder;

class TodoSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $userOne = factory(User::class)->create([
            'name' => 'John Doe'
        ]);

        $userTwo = factory(User::class)->create([
            'name' => 'Anne Doe'
        ]);

//        TODOS by this month

        factory(Todo::class, 15)->create([
            'user_id' => $userOne,
            'status' => true
        ]);

        factory(Todo::class, 20)->create(['user_id' => $userOne]);

        factory(Todo::class, 14)->create([
            'user_id' => $userTwo,
            'status' => true
        ]);

        factory(Todo::class, 23)->create(['user_id' => $userTwo]);

//        TODOS ONE MONTH AGO

        factory(Todo::class, 5)->create([
            'user_id' => $userOne,
            'status' => true,
            'created_at' => now()->subMonth()
        ]);

        factory(Todo::class, 10)->create(['user_id' => $userOne, 'created_at' => now()->subMonth()]);

        factory(Todo::class, 4)->create([
            'user_id' => $userTwo,
            'status' => true,
            'created_at' => now()->subMonth()
        ]);

        factory(Todo::class, 13)->create(['user_id' => $userTwo, 'created_at' => now()->subMonth()]);

//        TODOS TWO MONTHS AGO

        factory(Todo::class, 8)->create([
            'user_id' => $userOne,
            'status' => true,
            'created_at' => now()->subMonths(2)
        ]);

        factory(Todo::class, 16)->create(['user_id' => $userOne, 'created_at' => now()->subMonths(2)]);

        factory(Todo::class, 14)->create([
            'user_id' => $userTwo,
            'status' => true,
            'created_at' => now()->subMonths(2)
        ]);

        factory(Todo::class, 23)->create(['user_id' => $userTwo, 'created_at' => now()->subMonths(2)]);


    }
}

Enter fullscreen mode Exit fullscreen mode

Add Todo seeder

Go to database/seeds/DatabaseSeeders.php and add the Todo seeder in run method as the code below:

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(TodoSeeder::class);
    }
} 
Enter fullscreen mode Exit fullscreen mode

Now run the migrations

Go to your terminal/console/bash/cmd and type the next commands:

php artisan migrate
php artisan db:seed
Enter fullscreen mode Exit fullscreen mode

Add a route

For this tutorial I will create a controller for charts, executing the artisan command:

php artisan make:controller ChartController
Enter fullscreen mode Exit fullscreen mode

Then go to routes/web.php and add the next route:

Route::get('chart', ChartController::class); 
Enter fullscreen mode Exit fullscreen mode
  • This controller will only have one method so in Route get method I can pass as second param the controller class and Laravel will load the __invoke method if it exists.

The controller content:


namespace App\Http\Controllers;

use App\Todo;
use App\User;
use ArielMejiaDev\LarapexCharts\Facades\LarapexChart;
use Illuminate\Http\Request;

class ChartController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function __invoke()
    {
        $user        = User::first();
        $userTwo     = User::find(2);
        $todosDone   = Todo::where('user_id', $user->id)->whereStatus(true)->count();
        $todosNotYet = Todo::where('user_id', $user->id)->whereStatus(false)->count();

        $chart = LarapexChart::setTitle('Your Todos Stats')
            ->setLabels(['Done', 'Not Yet'])
            ->setDataset([$todosDone, $todosNotYet]);


        return view('chart', compact('chart'));
    }


}

Enter fullscreen mode Exit fullscreen mode

Create a view file

Next is necesary to create a blade file to render the chart, go to resources/views and create a file called "chart.blade.php"

add the next code to your view:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Todos Chart</title>
</head>
<body>

    {!! $chart->container() !!}


    <script src="{{ $chart->cdn() }}"></script>
    {!! $chart->script() !!}

</body>
</html> 
Enter fullscreen mode Exit fullscreen mode

Now open your project

In the browser with your project basepath and "/chart" you will see:

Alt Text

Congrats! now you are implementing apex charts in your Laravel project.

More?

This is a simple example but, maybe you really want to create more complex charts, so go on this.

In your ChartController.php change the last content with this:

namespace App\Http\Controllers;

use App\Todo;
use App\User;
use ArielMejiaDev\LarapexCharts\Facades\LarapexChart;
use Illuminate\Http\Request;

class ChartController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function __invoke()
    {

        $user = User::first();
        $userTwo = User::find(2);

        $usercurrentMonthTodos = Todo::where('user_id', $user->id)->whereStatus(true)->whereMonth('created_at', '=', now()->month)->count();
        $userTodosAMonthAgo = Todo::where('user_id', $user->id)->whereStatus(true)->whereMonth('created_at', '=', now()->subMonth()->month)->count();
        $userTodosTwoMonthAgo = Todo::where('user_id', $user->id)->whereStatus(true)->whereMonth('created_at', '=', now()->subMonths(2)->month)->count();

        $userTwocurrentMonthTodos = Todo::where('user_id', $userTwo->id)->whereStatus(true)->whereMonth('created_at', '=', now()->month)->count();
        $userTwoTodosAMonthAgo = Todo::where('user_id', $userTwo->id)->whereStatus(true)->whereMonth('created_at', '=', now()->subMonth()->month)->count();
        $userTwoTodosTwoMonthAgo = Todo::where('user_id', $userTwo->id)->whereStatus(true)->whereMonth('created_at', '=', now()->subMonths(2)->month)->count();

        $chart = LarapexChart::setType('line')
            ->setLabels([$user->name, $userTwo->name])
            ->setXAxis(['Now', 'A month ago', '2 months ago'])
            ->setDataset([
            [
                'username' => $user->name,
                'data' => [
                    $usercurrentMonthTodos, $userTodosAMonthAgo, $userTodosTwoMonthAgo
                ]
            ],
            [
                'username' => $userTwo->name,
                'data' => [
                    $userTwocurrentMonthTodos, $userTwoTodosAMonthAgo, $userTwoTodosTwoMonthAgo
                ]
            ]
        ]);


        return view('chart', compact('chart'));
    }


} 
Enter fullscreen mode Exit fullscreen mode

This will load a line chart with two different series of data

Alt Text

You can change the value in setType() method to add this types:

  • area
  • bar
  • heatmap

You can even change the colors of the chart by adding the method setColors(), to the chart instance like this:

$chart = LarapexChart::setType('line')
            ->setLabels([$user->name, $userTwo->name])
        ->setXAxis(['Now', 'A month ago', '2 months ago'])
        ->setColors(['#ffc73c', '#f5746f'])
Enter fullscreen mode Exit fullscreen mode

To get more examples and documentation of LarapexCharts go to LarapexCharts Documentation site

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .