Simple task for build graphic representation of cake schema based on graphwiz.

For this task need to have installed graphviz in path or use “-tool path/to/graphwiz/dot”

Graphviz youcan dowload from  http://www.graphviz.org/Download..php 

 Live example was generated on well known aplication – Bakery. I also include bakery schema made in designer. For me generated graphviz schema looks more pretty and easier to explore.

Bakery DBDesigner schema.

Example of schema – bakery application

<?php/**
 * 
 * 
 * PHP versions 4 and 5
 *
 * Copyright (c) Tomenko Yevgeny
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 */
uses(‘Folder’,‘File’,‘model’.DS.‘connection_manager’
);class VisualizeShell extends Shell {       var $DOC_DIR ;
    var 
$PREFIX
;
    var 
$graphToolPath ‘dot.exe’
;
// cake visualize -tool C:\dev\_tools_\graphviz-2.16\bin\dot.exe
    
function help
() {
        
$this->out(‘CakePHP visualise:’
);
        
$this->out(“cake visualise [-tool graphVizTool]”
);
        
$this->hr
();
    }
    function initialize() {
        
$this->DOC_DIR APP “doc”
;
        
$this->PREFIX“img_”
;
        if (isset(
$this->params[‘tool’
])) {
            
$this->graphToolPath =$this->params[‘tool’
];
        }
        return 
true
;
    }    
    function 
main
() { 
        
$this->help
();
        
$this->doVisualize
();    
    }
    
    function 
getSchemaInfo($modelName,$table_name
) {
        
$attrs 
= array();
        if (
App::import(‘model’,$modelName
)) {
            
$model = & new $modelName
();
            
$attrs=$model->schema
();
            return 
$attrs
;
        } else {
            
$DynamicModel = new Model(array(‘name’=> $modelName‘table’=> $table_name
)); 
            
$attrs=$DynamicModel->schema
();
            return 
$attrs
;
        }
        return 
false
;
    }     
    
    
    function 
doVisualize
() {
        
$header=$this->PREFIX+strftime(‘%Y-%m-%d %H:%M:%S’,time
());
        
$version=0
;
        if (
$version 0
) {
          
$header .= “\\nSchema version $version”
;
        }
        
$tableInfos 
= array();
        foreach(
$this->getAllTables() as $table_name
) {
            
$this->out(“Looking at table: {$table_name}”
);
            
$modelName=$this->_modelName($table_name
);
            
$tableInfos[$modelName] = $this->getSchemaInfo($modelName,$table_name
);
        }
        if (!file_exists($this->DOC_DIR) || !is_dir($this->DOC_DIR)) {
            
$this->out(“Creating directory \”{$this->DOC_DIR}\”…”
);
            
$folder = & new Folder($this->DOC_DIRtrue
);
        }
        
$this->writeDotFile($header$this->DOC_DIR$tableInfos
);
    }       function 
getAllTables($useDbConfig ‘default’
) {
        
$db =& ConnectionManager::getDataSource($useDbConfig
);
        
$usePrefix = empty($db->config[‘prefix’]) ? ” $db->config[‘prefix’
];
        if (
$usePrefix
) {
            
$tables 
= array();
            foreach (
$db->listSources() as $table
) {
                if (!
strncmp($table$usePrefixstrlen($usePrefix
))) {
                    
$tables[] = substr($tablestrlen($usePrefix
));
                }
            }
        } else {
            
$tables $db->listSources
();
        }
        
$this->__tables $tables
;
        return 
$tables
;
    }
    function writeDotFile($header$target_dir$tableInfos) {
        
$tmp_dot_file $target_dir .DS“model_information.dot”
;        $f = & new File($tmp_dot_filetrue
);
        
        
// Define a graph and some global settings
        
$f->append(“digraph G {\n”
);
        
$f->append(“\toverlap=false;\n”
);
        
$f->append(“\tsplines=true;\n”
);
        
$f->append(“\tnode [fontname=\”Helvetica\”,fontsize=9];\n”
);
        
$f->append(“\tedge [fontname=\”Helvetica\”,fontsize=8];\n”
);
        
$f->append(“\tranksep=0.1;\n”
);
        
$f->append(“\tnodesep=0.1;\n”
);
//    $f->append(“\tedge [decorate=\”true\”];\n”);        // Write header info
        $f->append(“\t_schema_info [shape=\”plaintext\”, label=\”{$header}\”, fontname=\”Helvetica\”,fontsize=8];\n”);
        
        
$assocs 
= array();
        
// Draw the tables as boxes
        
foreach ($tableInfos as $table=>$attributes
) {
          
$attrs “”
;
          if (
is_array($attributes) && count($attributes)>0
) {
              foreach (
$attributes as $attrname=>$attr
) {
                if (
substr($attrname, –3) == ‘_id’
) { 
                  
# Create an association to other table
                  
$table_name Inflector::camelize(r(‘_id’,,$attrname
));
                  if (!empty(
$tableInfos[$table_name
])) {
                    
$other_table $tableInfos[$table_name
];
                    
$assocs[] = array(‘label’=> $attrname‘node1’=> $table‘node2’=> $table_name
);
                  }
                }
                if (!empty(
$attr[‘length’])) $attr[‘type’].=“[{$attr[‘length’]}]”
;
                
$attrtype=$attr[‘type’
];
                
$attrs .= “{$attrname} : {$attrtype}”
;
                if (!empty(
$attr[‘default’])) $attrs .= “, default: \\\”{$attr[‘default’]}\\\””
;
                
$attrs .= “\\n”
;
              }
          }
          
$f->append(“\t\”{$table}\” [label=\”{{$table}|{$attrs}}\” shape=\”record\”];\n”
);
        }
        
// Draw the relations
        
foreach ($assocs as $assoc
) {
          
$f->append(“\t\”{$assoc[‘node1’]}\” -> \”{$assoc[‘node2’]}\” [label=\”{$assoc[‘label’]}\”]\n”
);
        }
        
        
// Close the graph
        
$f->append(“}\n”
);
        
$f->close
();        
// Create the images by using dot and neato (grapviz tools)
        // We’ll create several images with different layout. There is no “prefect” layout algorithm that suits all models
        
$this->createImg($this->graphToolPath“-Gmode=hier”$tmp_dot_file$target_dir .DS“model_overview_neato_hier”
);
        
$this->createImg($this->graphToolPath“”$tmp_dot_file$target_dirDS“model_overview_neato_plain”
);
        
        
// Remove the .dot file
        
$f->delete
();
        
    }     
  
    function 
createImg($app$args$dot_file$img_file_base
) {        
        
$img_file “$img_file_base.png”
;
        
$command “{$app} {$args} -Tpng  -o\”{$img_file}\” \”{$dot_file}\””
;
        
system($command,$retval
);
        if (!
$retval
) {
            
$this->out(“Generated {$img_file}\n”
);
        } else {
            
$this->out(“Failed to execute the ‘{$app}’ command! Is grapviz (www.graphviz.org) installed?\n”
);          
        }
    }     
    
    
 
    
}
?>

Advertisements