Laravel

Laravelでガントチャート

久しぶりの投稿になりました。

今日は、dhtmlxGanttというJsライブラリーをlaravelから使用してガントチャートを利用してみたいと思います。

ガントチャートは、プロジェクト管理や、工程管理には必須だと思いますので、是非使用してみて下さい。

Laravelプロジェクトの作成

開発環境はそれぞれの、お好きなものを使用していただいて構いません。
XAMPPやMAMPなどでも問題なく動作します。

ルートディレクトリーで、ターミナルもしくはコマンドプロンプトを開き
下記を入力して下さい。

composer create-project laravel/laravel gantt-demo

今回のサンプルでは、バージョンの問題は無いので、バージョン指定していませんが、バージョンを指定したプロジェクトを作成したい場合、この段階で指定してプロジェクトを作成して下さい。

プロジェクトディレクトリに移動し、ローカルサーバーを立ち上げます。

cd gantt-demo
php artisan serve

localhost:8000にアクセスして上図の画面が表示できれば、プロジェクトの作成は問題ありません。

Viewの作成(ガントチャート表示ページ)

まず、ガントチャートを表示するためのページを作成します。

本来なら、Layoutを分けてViewを定義すべきですが、ガントチャートの使い方をメインに説明したいので、細かい部分は省略します。

今後、しっかりしたチュートリアルを作成予定です。

resources/views/gantt_demo.blade.phpを作成し、下のコードをペーストして下さい。

<!DOCTYPE html>
<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <!-- 今回はCDNを使用 -->
    <script src="https://cdn.dhtmlx.com/gantt/edge/dhtmlxgantt.js"></script>
    <link href="https://cdn.dhtmlx.com/gantt/edge/dhtmlxgantt.css" rel="stylesheet">
 
    <style>
        html, body{
            height:100%;
            padding:0px;
            margin:0px;
            overflow: hidden;
        }
    </style>
</head>
<body>
<div id="gantt_here" style='width:100%; height:100%;'>
<!-- ここに表示します。-->
</div>

<script>
    gantt.init("gantt_here");
</script>
</body>

公式ページより、ダウンロードして使用しても良いのですが、今回は簡単なサンプルなので、CDNを利用します。

説明の必要がないくらい簡単なコードですね。

Webルートの定義

先ほど作成したViewを表示するためのルートを
routes/web.php
へ追記します。

Route::get('/', function () {
    return view('gantt_demo');
});

マイグレーション

それでは、DBにデータを保存するための準備を行います。

まず、プロジェクトディレクトリ直下の.envにデーターベースの接続情報を追記して下さい。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=gantt-demo
DB_USERNAME=username
DB_PASSWORD=userpassword

ターミナルでプロジェクトディレクトリーへ移動し、modelとマイグレーションファイルを作成します。

php artisan make:model Task --migration
php artisan make:model Link --migration

上記を実行することで、app/Task.phpLink.phpというモデルファイルと、database/migrations/に、それぞれのテーブルのマイグレーションファイルが出来上がっていると思います。

テーブル構造の定義

それでは、マイグレーションファイルを編集し、データベースへテーブルを作成したいと思います。

まず、「database/migrations/****_**_**_******_create_tasks_table.php
を下記の通り編集して下さい。

<?php
 
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
 
class CreateTasksTable extends Migration
{
    public function up()
    {
        Schema::create('tasks', function (Blueprint $table){
            $table->increments('id');
            $table->string('text');
            $table->integer('duration');
            $table->float('progress');
            $table->dateTime('start_date');
            $table->integer('parent');
            $table->timestamps();
        });
    }
 
    public function down()
    {
        Schema::dropIfExists('tasks');
    }
}

続いて、「database/migrations/****_**_**_******_create_links_table.php
も書きの通り編集して下さい。

<?php
 
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
 
class CreateLinksTable extends Migration
{
    public function up()
    {
        Schema::create('links', function (Blueprint $table) {
            $table->increments('id');
            $table->string('type');
            $table->integer('source');
            $table->integer('target');
            $table->timestamps();
        });
    }
 
    public function down()
    {
        Schema::dropIfExists('links');
    }
}

タスクテーブルは、プロジェクトやタスクを管理するメインテーブルで、リンクテーブルは、タスク間の繋がりを表すテーブルです。

準備ができたら、ターミナルより、下記コマンドを実行して、マイグレーションファイルを摘要します。

php artisan migrate

シードデータの作成

ガントチャートを確認するために、とりあえず、タスクテーブルのシードデータを作成します。
※余裕がある方は、リンクテーブルもシードデータを作成して下さい。

php artisan make:seeder TasksTableSeeder

database/seeds/TasksTableSeeder.phpが出来上がるので、下記の様に編集して下さい。

<?php
 
use Illuminate\Database\Seeder;
 
class TasksTableSeeder extends Seeder
{
    public function run()
    {
        DB::table('tasks')->insert([
            ['id'=>1, 'text'=>'テストプロジェクト', 'start_date'=>'2020-08-01 00:00:00', 
                'duration'=>5, 'progress'=>0.8, 'parent'=>0],
            ['id'=>2, 'text'=>'テストタスク', 'start_date'=>'2020-08-06 00:00:00', 
                'duration'=>4, 'progress'=>0.5, 'parent'=>1],
            ['id'=>3, 'text'=>'テストタスク - 2', 'start_date'=>'2020-08-05 00:00:00', 
                'duration'=>6, 'progress'=>0.7, 'parent'=>1],
            ['id'=>4, 'text'=>'テストタスク - 3', 'start_date'=>'2020-08-07 00:00:00', 
                'duration'=>2, 'progress'=>0, 'parent'=>1],
            ['id'=>5, 'text'=>'テストタスク - 1.1', 'start_date'=>'2020-08-05 00:00:00', 
                'duration'=>5, 'progress'=>0.34, 'parent'=>2],
            ['id'=>6, 'text'=>'テストタスク - 1.2', 'start_date'=>'2020-08-11 00:00:00', 
                'duration'=>4, 'progress'=>0.5, 'parent'=>2],
            ['id'=>7, 'text'=>'テストタスク - 2.1', 'start_date'=>'2020-08-07 00:00:00', 
                'duration'=>5, 'progress'=>0.2, 'parent'=>3],
            ['id'=>8, 'text'=>'テストタスク - 2.2', 'start_date'=>'2020-08-06 00:00:00', 
                'duration'=>4, 'progress'=>0.9, 'parent'=>3]
        ]);
    }
}

続いて、シードをデータベースへ投入するために下記ファイルを編集します。
database/seeds/DatabaseSeeder.php

<?php
 
use Illuminate\Database\Seeder;
 
class DatabaseSeeder extends Seeder
{
    public function run()
    {
        $this->call(TasksTableSeeder::class);
    }
}

編集が終わったら、ターミナルで、下記コマンドを実行して下さい。

php artisan db:seed

これで、ダミーデータを投入できました。
ここまでで、準備は終了です。

お疲れ様でした。

ガントチャートの表示

それでは、データベースのデータを使用してガントチャートを表示していきたいと思います。

まず、「app/Task.php」を下記の様に編集して下さい。

<?php
 
namespace App;
 
use Illuminate\Database\Eloquent\Model;
 
class Task extends Model
{
    protected $appends = ["open"];
 
    public function getOpenAttribute(){
        return true;
    }
}

コードの意味合いとしては、今回DBにOpenフラグを省略したので、JSONデータに「open」という開閉状態のフラグを付与するためです。

データ取得APIの作成

まず、ターミナルで下記コマンドを実行し、コントローラーを作成します。

php artisan make:controller GanttController

コントローラーができたらDBデータを取得して、JSONを返却するコードを書きます。

app/Http/Controllers/GanttController.php

<?php
namespace App\Http\Controllers;
use App\Task;
use App\Link;
 
class GanttController extends Controller
{
    public function get(){
        $tasks = new Task();
        $links = new Link();
 
        return response()->json([
            "data" => $tasks->all(),
            "links" => $links->all()
        ]);
    }
}

続いて、APIアクセスを処理するルーティングを記述します。
web.phpではないので注意して下さい。

routes/api.php

<?php
 
use Illuminate\Http\Request;
 
Route::get('/data', 'GanttController@get');

/dataでアクセスを受けたときにJSONデータを返却します。
この状態で、ブラウザでアクセスすると、JSONデータの確認が可能です。
※長くなっているので、画像は省略します。

viewの編集

続いて、ビューから、APIを叩くためのコードを記述します。

resources/views/gantt_demo.blade.phpを開き、スクリプトタグ内に、下記を追記して下さい。

// ~略~
gantt.init("gantt_here");
 
gantt.load("/api/data");  // この行を追記

これで、先ほどコントローラーに記述した処理を呼び出し、データベースからデータの取得が可能になっています。

ローカルサーバーを立ち上げて、’localhost:8000’へアクセスしてみて下さい。
ここまでに間違いがなければ、データが表示されているかと思います。

このままでは、日付が少々見にくいので、下記をviewへ追記します。

// ~略~
gantt.config.date_format = "%Y-%m-%d %H:%i:%s"; //この行を追記

gantt.init("gantt_here");

これで下の画像の様に表示ができたかと思います。

データーの追加・編集・削除

ただ表示するだけなら、上の状態で良いのですが、おそらくガントチャートを利用する場合、編集作業はつきものだと思います。

このライブラリーは、マウス操作で、直感的に編集可能です。

ただ、ライブラリーの機能で、画面上で編集できたとしても、データベースに保存できないと意味がありません。

そこで、APIを利用して、Laravel側でデータを保存・削除などできる様に編集します。

まず、「TaskController」を作成し、次の様に記述して下さい。

app/Http/Controllers/TaskController.php

<?php
namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
use App\Task;
 
class TaskController extends Controller
{
    public function store(Request $request){
 
        $task = new Task();
 
        $task->text = $request->text;
        $task->start_date = $request->start_date;
        $task->duration = $request->duration;
        $task->progress = $request->has("progress") ? $request->progress : 0;
        $task->parent = $request->parent;
 
        $task->save();
 
        return response()->json([
            "action"=> "inserted",
            "tid" => $task->id
        ]);
    }
 
    public function update($id, Request $request){
        $task = Task::find($id);
 
        $task->text = $request->text;
        $task->start_date = $request->start_date;
        $task->duration = $request->duration;
        $task->progress = $request->has("progress") ? $request->progress : 0;
        $task->parent = $request->parent;
 
        $task->save();
 
        return response()->json([
            "action"=> "updated"
        ]);
    }
 
    public function destroy($id){
        $task = Task::find($id);
        $task->delete();
 
        return response()->json([
            "action"=> "deleted"
        ]);
    }
}

基本的な、CRUD操作を記載しているだけなので、難しくはないと思います。

続いて、APIを実行する為のルーティングを記載します。

routes/api.phpへ下記を追記して下さい。

Route::resource('task', 'TaskController');

resourceについての詳しい説明は、Laravel公式ドキュメントが、とても分かりやすいです。

続いて、「LinkController」を作成し、下のコードを記述します。

app/Http/Controllers/LinkController.php

<?php
namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
use App\Link;
 
class LinkController extends Controller
{
    public function store(Request $request){
        $link = new Link();
 
        $link->type = $request->type;
        $link->source = $request->source;
        $link->target = $request->target;
 
        $link->save();
 
        return response()->json([
            "action"=> "inserted",
            "tid" => $link->id
        ]);
    }
 
    public function update($id, Request $request){
        $link = Link::find($id);
 
        $link->type = $request->type;
        $link->source = $request->source;
        $link->target = $request->target;
 
        $link->save();
 
        return response()->json([
            "action"=> "updated"
        ]);
    }
 
    public function destroy($id){
        $link = Link::find($id);
        $link->delete();
 
        return response()->json([
            "action"=> "deleted"
        ]);
    }
}

ルーティングも先ほど同様、追記します。

routes/api.php

Route::resource('link', 'LinkController');

最後に、ブラウザー操作で編集した内容を、APIへ投げる為に、ビューを編集します。
スクリプトタグ内に、下記を追記して下さい。

resources/views/gantt_demo.blade.php

gantt.load("/api/data");
 
var dp = new gantt.dataProcessor("/api"); // 追記
dp.init(gantt); // 追記
dp.setTransactionMode("REST"); // 追記

これで、ブラウザー操作の変更も、データベースへ反映されているかと思います。

とても簡単でしたね。

まとめ

とても久しぶりの記事になりました。
最近は、LaravelやVue.jsを使用することが増えたので、業務で身についた技術を、どんどん発信していきたいと思います。

今回は、すごく簡単なサンプルでしたが、dhtmlxは非常に多機能で使用するのに、学習コストが高いです。

ガントチャートは、比較的利用される事が多いと思いますので、更に発展的な利用方法を、今後は取り上げていきたいと思います。

また、Laravelのチュートリアル的な内容も記事にしていきたいと考えています。

今後もよろしくお願いします。