#!/usr/bin/php */ require_once(__DIR__ . "/../src/Dblayeroo.php"); /** * modelGraph * Allow to create the relational graph of an existing database * Use GraphViz to generate the graph * Request the database DSN to operate */ class Modelgraph { // PROPERTIES /** * The connected object dblayeroo */ private $db; /** * The output file */ private $output; /** * The constructor wait for $dsn * @param string $dsn The DSN to connect to database * @param string $username The username to connect to database * @param string $password The password to connect to database * @param string $output The output file to generate */ public function __construct($dsn, $username, $password, $output) { $this->output = $output; $this->db = new Domframework\Dblayeroo($dsn, $username, $password); $this->graphvizCommande(); } /** * Generate the output file */ public function generate() { $tables = []; foreach ($this->db->listTables() as $table) { $tables[$table] = $this->db->getTableSchema($table); } $d = "digraph G {\n"; $d .= " graph [\n"; $d .= " label = <" . "Database " . $this->db->databasename() . "
" . "" . date("Y-m-d") . "" . ">\n"; $d .= " ]\n"; $d .= " node [\n"; $d .= " shape=box\n"; $d .= " fontname = \"helvetica\"\n"; $d .= " ];\n"; $d .= " rankdir=RL\n"; // Generate the tables objects with the fields foreach ($tables as $table => $schema) { $d .= " /** * TABLE '$table' */\n"; $d .= " \"$table\" [\n"; $d .= " shape = \"plaintext\"\n"; $d .= " label = <\n"; $d .= " \n"; // Display the name of the table as title $d .= " \n"; // Display the fields $i = 0; foreach ($schema["fields"] as $field => $params) { $d .= " \n"; $d .= " \n"; $d .= " \n"; $d .= " \n"; $d .= " \n"; $i++; } $d .= "
"; $d .= "$table
"; if (key_exists($field, $schema["foreign"])) { // Foreign Key $d .= "!"; } elseif ( key_exists("primary", $schema) && $field === $schema["primary"] ) { $d .= "🔑"; } elseif (in_array("not null", $params)) { // Primary key found $d .= ""; } else { // NOT NULL $d .= "◇"; } $d .= ""; $d .= $field; $d .= ""; $d .= $params[0]; $d .= "
>\n"; $d .= " ];\n"; } // Generate the links between the tables foreach ($tables as $table => $schema) { // "node1":"f2" -> "node5":"f0" []; foreach ($schema["foreign"] as $field => $params) { $d .= "\"$table\":\"OUT-$field\" -> \"" . $params[0] . "\":\"IN-" . $params[1] . "\" "; $d .= "[];\n"; } } $d .= "}\n"; //echo $d; $this->createJPG($d); } /** * Look for the dot command * @return the full path of 'dot' command */ private function graphvizCommande() { foreach (explode(":", getenv("PATH")) as $path) { if (file_exists("$path/dot")) { return "$path/dot"; } } throw new \Exception( "Can not find 'dot' executable. Install graphviz", 500 ); } /** * Generate the JPEG file with graphviz * @param string $content The content of the GV file */ private function createJPG($content) { $tmp = tempnam("/tmp", "modelgraph_"); file_put_contents($tmp, $content); $cmd = $this->graphvizCommande() . " -T jpeg $tmp " . "-o " . escapeshellarg($this->output) . " 2>&1"; exec($cmd, $output); unlink($tmp); if (!empty($output)) { echo "ERROR : " . implode("\n", $output); exit(2); } } } // MAIN PROGRAM if (isset($argv[1]) && $argv[1] === "-h") { echo "Create the ER Diagram of a SQL database\n"; echo "Usage : \n"; echo $argv[0] . " DSN username password outputfile.jpg\n"; echo "DSN Examples : 'mysql:dbname=databaseName'\n"; } if (! isset($argv[1])) { die("No DSN provided\n"); } if (! isset($argv[2])) { die("No username provided\n"); } if (! isset($argv[3])) { die("No password provided\n"); } if (! isset($argv[4])) { die("No output file provided\n"); } $modelgraph = new Modelgraph($argv[1], $argv[2], $argv[3], $argv[4]); $modelgraph->generate();