Diese Anleitung beschreibt, wie ein Gantt-Diagramm auf PHP-Basis mit dem Slim 4 Framework und einer RESTful API auf dem Server eingerichtet wird.
Diese Anleitung gilt für Slim Framework v4.x. Wenn Sie mit einer älteren Version arbeiten, schauen Sie sich die Slim Framework v3.x Anleitung an.
Es gibt auch Tutorials zur Integration mit anderen Plattformen und Frameworks:
Dieses Beispiel verwendet Slim 4 für das Routing und MySQL für die Datenspeicherung. Die CRUD-Logik ist mit PDO aufgebaut und soll an andere Frameworks anpassbar sein.
Der vollständige Quellcode ist auf GitHub verfügbar.
Wir verwenden die Skeleton-Anwendung für das Slim 4 Framework.
Beginnen Sie mit dem Import des Projekts und der Installation mit Composer:
php composer.phar create-project slim/slim-skeleton gantt-rest-php
Falls Composer global installiert ist, können Sie stattdessen Folgendes ausführen:
composer create-project slim/slim-skeleton gantt-rest-php
Überprüfen Sie als Nächstes, ob alles funktioniert. Navigieren Sie zum Anwendungsverzeichnis und starten Sie einen Webserver:
cd gantt-rest-php
php -S 0.0.0.0:8080 -t public public/index.php
Öffnen Sie anschließend http://127.0.0.1:8080 in Ihrem Browser. Sie sollten die Standard-Slim-Seite sehen.
Erstellen wir nun eine Seite, die das Gantt-Diagramm enthält. Dieser Prozess umfasst zwei einfache Schritte.
Erstellen Sie eine Datei namens basic.html im Ordner app/templates
. Diese Datei enthält das Gantt-Diagramm und dessen notwendige Einrichtung zum Laden von Daten.
Hier ist der vollständige Code:
app/templates/basic.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<script src="https://cdn.dhtmlx.com/gantt/edge/dhtmlxgantt.js"></script>
<link href="https://cdn.dhtmlx.com/gantt/edge/dhtmlxgantt.css" rel="stylesheet">
<style type="text/css"> html, body{
height:100%;
padding:0px;
margin:0px;
overflow: hidden;
}
</style>
</head>
<body>
<div id="gantt_here" style='width:100%; height:100%;'></div>
<script type="text/javascript"> gantt.init("gantt_here");
</script>
</body>
</html>
Dieser Code erstellt ein leeres Gantt-Diagramm auf der Seite. Benutzer können Aufgaben und Verknüpfungen hinzufügen und bearbeiten, aber Änderungen bleiben nach dem Neuladen der Seite nicht bestehen.
Um die neue Seite im Browser zugänglich zu machen, fügen Sie app/routes.php eine Route hinzu:
app/routes.php
$app->get('/', function (Request $request, Response $response) {
$payload = file_get_contents(__DIR__.'/templates/basic.html');
$response->getBody()->write($payload);
return $response;
});
Starten Sie die App neu:
command line
php -S 0.0.0.0:8080 -t public public/index.php
Öffnen Sie nun http://127.0.0.1:8080/ in Ihrem Browser, um das Gantt-Diagramm auf der Seite zu sehen.
Zu diesem Zeitpunkt wird das Gantt-Diagramm angezeigt, speichert jedoch keine Daten. Der nächste Schritt besteht darin, eine Datenbank einzurichten und sie mit der Anwendung zu verbinden.
Sie können eine Datenbank mit Ihrem bevorzugten MySQL-Client wie phpMyAdmin oder direkt über die Konsole einrichten. Unten ist ein Beispiel für SQL-Code, um eine grundlegende Datenbank mit zwei Tabellen zu erstellen.
CREATE DATABASE IF NOT EXISTS `gantt`;
USE `gantt`;
CREATE TABLE `gantt_links` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`source` int(11) NOT NULL,
`target` int(11) NOT NULL,
`type` varchar(1) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `gantt_tasks` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`text` varchar(255) NOT NULL,
`start_date` datetime NOT NULL,
`duration` int(11) NOT NULL,
`progress` float NOT NULL,
`parent` int(11) NOT NULL,
PRIMARY KEY (`id`)
);
Sobald die Datenbank eingerichtet ist, können Sie einige Beispieldaten in die Tabelle gantt_tasks zur Testzwecken hinzufügen. Hier ist ein einfaches Beispiel:
INSERT INTO `gantt_tasks` VALUES ('1', 'Project #1', '2020-03-31 00:00:00',
'4', '0.8', '0');
INSERT INTO `gantt_tasks` VALUES ('2', 'Task #1', '2020-03-31 00:00:00',
'3', '0.5', '1');
INSERT INTO `gantt_tasks` VALUES ('3', 'Task #2', '2020-04-01 00:00:00',
'2', '0.7', '1');
INSERT INTO `gantt_tasks` VALUES ('4', 'Task #3', '2020-04-02 00:00:00',
'2', '0', '1');
INSERT INTO `gantt_tasks` VALUES ('5', 'Task #1.1', '2020-04-03 00:00:00',
'3', '0.34', '2');
INSERT INTO `gantt_tasks` VALUES ('6', 'Task #1.2', '2020-04-03 13:22:17',
'2', '0.5', '2');
INSERT INTO `gantt_tasks` VALUES ('7', 'Task #2.1', '2020-04-04 00:00:00',
'3', '0.2', '3');
INSERT INTO `gantt_tasks` VALUES ('8', 'Task #2.2', '2020-04-05 00:00:00',
'2', '0.9', '3');
Für ein detaillierteres Beispiel schauen Sie sich diese Anleitung an.
Mit der Datenbank und den Beispieldaten können Sie mit dem Laden der Daten fortfahren.
Arbeiten wir nun am Laden von Daten aus der Datenbank. Auf der Client-Seite können Daten mit der Methode gantt.load abgerufen werden:
app/templates/basic.html
gantt.config.date_format = "%Y-%m-%d %H:%i:%s";
gantt.init("gantt_here");
gantt.load("/data");
Dies sendet eine AJAX-Anfrage an die angegebene URL und erwartet, dass die Antwort Gantt-Daten im JSON-Format enthält.
Der Parameter gantt.config.date_format
wird hier ebenfalls gesetzt, um das vom Datenquellen verwendete Datumsformat festzulegen, was das Parsen der Daten für den Client erleichtert.
Auf der Serverseite müssen Sie einen Handler für diese Anfrage erstellen. Öffnen Sie die Datei app/routes.php und fügen Sie eine neue Route hinzu:
app/routes.php
$app->get('/data', 'getGanttData');
Implementieren Sie als Nächstes die Logik für die Funktion getGanttData. Um die Dinge organisiert zu halten, können Sie alle Gantt-bezogenen Logiken in eine separate Datei legen. Erstellen Sie eine neue Datei app/gantt.php und fügen Sie den folgenden Code hinzu:
app/gantt.php
<?php
function getConnection()
{
return new PDO("mysql:host=localhost;dbname=gantt", "root", "root",
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);
}
function getGanttData($request, $response, $args) {
$db = getConnection();
$result = [
"data"=> [],
"links"=> []
];
foreach($db->query("SELECT * FROM gantt_tasks") as $row){
$row["open"] = true;
array_push($result["data"], $row);
}
foreach ($db->query("SELECT * FROM gantt_links") as $link){
array_push($result["links"], $link);
}
$payload = json_encode($result);
$response->getBody()->write($payload);
return $response->withHeader("Content-Type", "application/json");
};
Schließlich fügen Sie app/gantt.php in app/routes.php ein:
app/routes.php
<?php
declare(strict_types=1);
use App\Application\Actions\User\ListUsersAction;
use App\Application\Actions\User\ViewUserAction;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;
use Slim\Interfaces\RouteCollectorProxyInterface as Group;
// Fügen Sie dhtmlxGantt CRUD hinzu
require __DIR__ . "/gantt.php";
return function (App $app) {
$app->get("/", function (Request $request, Response $response) {
$payload = file_get_contents(__DIR__."/templates/basic.html");
$response->getBody()->write($payload);
return $response;
});
$app->get("/data", "getGanttData");
$app->group("/users", function (Group $group) {
$group->get("", ListUsersAction::class);
$group->get("/{id}", ViewUserAction::class);
});
};
Hier ist eine kurze Zusammenfassung des Codes:
Sobald dies erledigt ist, können Sie http://127.0.0.1:8080/ öffnen, um das Gantt-Diagramm mit den Testdaten zu sehen.
Der nächste Schritt besteht darin, die auf der Client-Seite vorgenommenen Änderungen zurück an den Server zu speichern. Dies wird typischerweise mit der eingebauten dataProcessor Bibliothek von Gantt erledigt. Fügen Sie den folgenden Code zu basic.html hinzu:
app/templates/basic.html
gantt.config.date_format = "%Y-%m-%d %H:%i:%s";
gantt.init("gantt_here");
gantt.load("/data");
var dp = new gantt.dataProcessor("/data");dp.init(gantt);dp.setTransactionMode("REST");
Hierbei hört der DataProcessor auf Client-seitige Aktionen wie Hinzufügen, Aktualisieren oder Löschen von Daten und sendet entsprechende AJAX-Anfragen an den Server. Der REST-Modus stellt sicher, dass unterschiedliche HTTP-Methoden für unterschiedliche Aktionen verwendet werden. Weitere Details zu den Routen finden Sie hier.
Um diese Routen in der App zu behandeln, aktualisieren Sie app/routes.php:
app/routes.php
<?php
declare(strict_types=1);
use App\Application\Actions\User\ListUsersAction;
use App\Application\Actions\User\ViewUserAction;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;
use Slim\Interfaces\RouteCollectorProxyInterface as Group;
// Fügen Sie dhtmlxGantt CRUD hinzu
require __DIR__ . "/gantt.php";
return function (App $app) {
$app->get("/", function (Request $request, Response $response) {
$payload = file_get_contents(__DIR__."/templates/basic.html");
$response->getBody()->write($payload);
return $response;
});
$app->get("/data", "getGanttData");
$app->post("/data/task", "addTask");
$app->put("/data/task/{id}", "updateTask");
$app->delete("/data/task/{id}", "deleteTask");
$app->post("/data/link", "addLink");
$app->put("/data/link/{id}", "updateLink");
$app->delete("/data/link/{id}", "deleteLink");
};
Implementieren Sie nun die mit diesen Routen verknüpften Methoden in app/gantt.php. Der Code für diese Methoden ist unkompliziert – sie behandeln das Erstellen, Aktualisieren und Löschen von Aufgaben und Verknüpfungen. Beim Einfügen wird die Datenbank-ID des neuen Elements an den Client zurückgesendet.
Der clientseitige Gantt behandelt standardmäßig verwandte Aufgaben und Verknüpfungen, sodass hier keine Datenbankbeziehungen verwaltet werden müssen. Wenn Sie diese jedoch auf der Serverseite verwalten möchten, können Sie die cascade_delete Konfiguration aktivieren.
Wenn alles bereit ist, führen Sie die Anwendung aus und öffnen Sie http://127.0.0.1:8080, um das voll funktionsfähige Gantt-Diagramm zu sehen.
Gantt ermöglicht das Umsortieren von Aufgaben mit Drag-and-Drop-Funktionalität. Um diese Funktion zu unterstützen, müssen Sie die Aufgabenreihenfolge in der Datenbank speichern. Weitere Details finden Sie hier.
Um Benutzern das Umsortieren von Aufgaben in der Benutzeroberfläche zu ermöglichen, beginnen Sie mit der Änderung der Konfiguration in der Datei basic.html. Aktualisieren Sie sie wie unten gezeigt:
app/templates/basic.html
gantt.config.order_branch = true;gantt.config.order_branch_free = true;
gantt.init("gantt_here");
Nehmen Sie als Nächstes Änderungen auf der Serverseite vor, um die Aufgabenreihenfolge in einer Spalte namens sortorder
zu speichern. Hier ist ein Beispiel, wie die aktualisierte Tabelle gantt_tasks aussehen könnte:
CREATE TABLE `gantt_tasks` (
`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`text` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`start_date` datetime NOT NULL,
`duration` int(11) NOT NULL,
`progress` float NOT NULL DEFAULT 0,
`parent` int(11) NOT NULL,
`sortorder` int(11) NOT NULL );
Wenn Sie bereits eine Tabelle haben, können Sie einfach die Spalte sortorder
hinzufügen:
ALTER TABLE `gantt_tasks` ADD COLUMN `sortorder` int(11) NOT NULL;
Aktualisieren Sie nun die CRUD-Operationen in app/gantt.php.
sortorder
sortiert zurückgeben:app/gantt.php
function getGanttData($request, $response, $args) {
$db = getConnection();
$result = [
"data" => [],
"links" => []
];
foreach ($db->query("SELECT * FROM gantt_tasks ORDER BY sortorder ASC") as $row) {
$row["open"] = true;
array_push($result["data"], $row);
}
foreach ($db->query("SELECT * FROM gantt_links") as $link) {
array_push($result["links"], $link);
}
$payload = json_encode($result);
$response->getBody()->write($payload);
return $response->withHeader("Content-Type", "application/json");
};
sortorder
-Wert erhält:app/gantt.php
function addTask($request, $response, $args) {
$task = getTask($request->getParsedBody());
$db = getConnection();
$maxOrderQuery = "SELECT MAX(sortorder) AS maxOrder FROM gantt_tasks";
$statement = $db->prepare($maxOrderQuery);
$statement->execute();
$maxOrder = $statement->fetchColumn();
if (!$maxOrder) {
$maxOrder = 0;
}
$task[":sortorder"] = $maxOrder + 1;
$query = "INSERT INTO gantt_tasks(text, start_date, duration, progress, parent, sortorder) ".
"VALUES (:text, :start_date, :duration, :progress, :parent, :sortorder)";
$db->prepare($query)->execute($task);
$result = [
"action" => "inserted",
"tid" => $db->lastInsertId()
];
$payload = json_encode($result);
$response->getBody()->write($payload);
return $response->withHeader("Content-Type", "application/json");
}
app/gantt.php
// update a task
function updateTask($request, $response, $args) {
$sid = $request->getAttribute("id");
parse_str(file_get_contents("php://input"), $body);
$task = [
"text" => $body["text"],
"start_date" => $body["start_date"],
"duration" => $body["duration"],
"progress" => $body["progress"],
"parent" => $body["parent"],
"sortorder" => $body["sortorder"]
];
$db = getConnection();
$query = "UPDATE gantt_tasks ".
"SET text = :text, start_date = :start_date, duration = :duration,".
"progress = :progress, parent = :parent, sortorder = :sortorder ".
"WHERE id = :sid";
$db->prepare($query)->execute(array_merge($task, [":sid" => $sid]));
if (isset($body["target"]) && $body["target"]) {
updateOrder($sid, $body["target"], $db);
}
$result = [
"action" => "updated"
];
$payload = json_encode($result);
$response->getBody()->write($payload);
return $response->withHeader("Content-Type", "application/json");
}
function updateOrder($taskId, $target, $db) {
$nextTask = false;
$targetId = $target;
if (strpos($target, "next:") === 0) {
$targetId = substr($target, strlen("next:"));
$nextTask = true;
}
if ($targetId == "null") {
return;
}
$sql = "SELECT sortorder FROM gantt_tasks WHERE id = :id";
$statement = $db->prepare($sql);
$statement->execute([":id" => $targetId]);
$targetOrder = $statement->fetchColumn();
if ($nextTask) {
$targetOrder++;
}
$sql = "UPDATE gantt_tasks SET sortorder = sortorder + 1 ".
"WHERE sortorder >= :targetOrder";
$statement = $db->prepare($sql);
$statement->execute([":targetOrder" => $targetOrder]);
$sql = "UPDATE gantt_tasks SET sortorder = :targetOrder WHERE id = :taskId";
$statement = $db->prepare($sql);
$statement->execute([
":targetOrder" => $targetOrder,
":taskId" => $taskId
]);
}
Ein einsatzbereites Demo ist auf GitHub verfügbar.
Alternativ können Sie ein PHP-Backend mit der Bibliothek dhtmlxConnector einrichten. Ein Schritt-für-Schritt-Tutorial ist hier verfügbar.
Beachten Sie, dass Gantt selbst nicht gegen Bedrohungen wie SQL-Injections, XSS oder CSRF-Angriffe schützt. Die Gewährleistung der Sicherheit der Anwendung liegt in der Verantwortung des Entwicklers. Weitere Details finden Sie hier.
Wenn Aufgaben und Verknüpfungen nach den Einrichtungsschritten nicht angezeigt werden, schauen Sie sich die Fehlerbehebungsanleitung in diesem Artikel an.
Sie haben nun ein voll funktionsfähiges Gantt-Diagramm. Der vollständige Code ist auf GitHub verfügbar, wo Sie ihn für Ihre Projekte klonen oder herunterladen können.
Für weitere Funktionen und Integrationen erkunden Sie die Anleitungen oder Tutorials zur Integration von Gantt mit anderen Backend-Frameworks.
Zurück nach oben