This complete guide documents UmlWriter 1.2.0, published on 2017-02-28.
This work is licensed under the Attribution-Share Alike 3.0 Unported license.
We distribute a PHP Archive (PHAR) that contains all required dependencies of UmlWriter bundled in a single file.
Make it executable, and put it into your $PATH
.
$ chmod +x umlwriter-1.2.0.phar $ mv umlwriter-1.2.0.phar /usr/local/bin/umlwriter $ umlwriter --version
You can also immediately use the PHAR after you have downloaded it.
$ wget http://bartlett.laurent-laville.org/get/umlwriter-1.2.0.phar $ php umlwriter-1.2.0.phar --version
With both methods then you have this output :
umlWriter version 1.2.0
UML diagrams produced, may be either :
The following diagram processors (output formats) are available:
Detailed descriptions and examples of the diagramming languages are available on the Graphviz and PlantUML websites. |
The following reverse-engines are supported:
In graphviz format with bartlett/php-reflect
reverse-engine
$ umlwriter diagram:render --reflector=reflect --processor=graphviz /path/to/data_source
In graphviz format with andrewsville/php-token-reflection
reverse-engine
$ umlwriter diagram:render --reflector=tokenreflection --processor=graphviz /path/to/data_source
In plantuml format with default reverse-engine (bartlett/php-reflect
)
$ umlwriter diagram:render --processor=plantuml /path/to/data_source
You must have installed correctly graphviz or plantuml before to continue. |
With Graphviz and png
output format
$ dot -Tpng -O /path/to/gv_file
Where /path/to/gv_file
is a file contening Graphviz syntax statements produced by
the umlwriter command.
With PlantUML and png
output format
$ java -jar plantuml.jar -Tpng /path/to/puml_file -o /path/to/ouput/dir
Where /path/to/puml_file
is a file contening PlantUML syntax statements produced by
the umlwriter command.
And /path/to/output/dir
is the directory where the image will be generated.
Let’s review what we’ve done :
png
image) from any data source.
First visit, you are highly recommended to follow chapters in following order. |
UmlWriter may be installed in several ways, choose your favorite.
Before you install PHP UmlWriter, you will need an operating system with PHP 5.4.0 or later installed,
UmlWriter requires the spl extensions. This extension is usually compiled and enabled by default.
Put a file named composer.json at the root of your project, with the content below:
{ "require": { "bartlett/umlwriter": "^1.2" } }
And ask Composer to install the dependencies:
$ php composer.phar install
Or just invoke Composer to install the latest version:
$ php composer.phar require bartlett/umlwriter
You can also use Composer to create a new project from an existing UmlWriter package. This is the equivalent of doing a git clone checkout followed by a composer install of the vendors. $ php composer.phar create-project bartlett/umlwriter /path/to/install ^1.2 Where |
The recommended way for newbies, or just to have a look on features of this library, is to download a PHP Archive that contain all required dependencies of PHP UmlWriter bundled in a single file.
$ wget http://bartlett.laurent-laville.org/get/umlwriter-1.2.0.phar $ chmod +x umlwriter-1.2.0.phar $ mv umlwriter-1.2.0.phar /usr/local/bin/umlwriter $ umlwriter
You can also immediately use the PHAR after you have downloaded it.
$ wget http://bartlett.laurent-laville.org/get/umlwriter-1.2.0.phar $ php umlwriter-1.2.0.phar
The command-line interface is the easiest way to try and learn the basic UmlWriter features.
For all users. |
When you invoke the umlwriter
command, you should obtain the following commands and options :
___ __ _ _ _ _ _ __ ___ | \ \ / / __(_) |_ ___ _ __ | | | | '_ ` _ \| |\ \ /\ / / '__| | __/ _ \ '__| | |_| | | | | | | | \ V V /| | | | || __/ | \__,_|_| |_| |_|_| \_/\_/ |_| |_|\__\___|_| umlWriter version 1.2.0 Usage: command [options] [arguments] Options: -h, --help Display this help message -q, --quiet Do not output any message -V, --version Display this application version --ansi Force ANSI output --no-ansi Disable ANSI output -n, --no-interaction Do not ask any interactive question --manifest Show which versions of dependencies are bundled. -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug Available commands: help Displays help for a command list Lists commands diagram diagram:render Generate diagram statements of all objects diagram:render:class Generate diagram statements of a single class diagram:render:namespace Generate diagram statements of a single namespace
diagram:render |
Generate diagram statements of all objects. $ umlwriter diagram:render --processor=graphviz src/Bartlett/UmlWriter/Processor digraph G { overlap = false; node [fontname="Verdana", fontsize="8", shape="none", margin="0", fillcolor="#FEFECE", style="filled"]; edge [fontname="Verdana", fontsize="8"]; subgraph cluster_0 { label="Bartlett\\UmlWriter\\Processor"; "Bartlett\\UmlWriter\\Processor\\AbstractProcessor" [label=< <table border="0" cellborder="1" cellspacing="0"> <tr><td align="center"><< <font color="black"><i>abstract</i></font> >><br/><b>AbstractProcessor</b></td></tr> <tr><td><table border="0" cellspacing="0" cellpadding="2"> <tr><td align="left"># reflector</td></tr> <tr><td align="left"># graphId</td></tr> <tr><td align="left"># objects</td></tr> <tr><td align="left"># edges</td></tr> <tr><td align="left">- spaces</td></tr> <tr><td align="left">- linebreak</td></tr> </table></td></tr> <tr><td><table border="0" cellspacing="0" cellpadding="2"> <tr><td align="left">+__construct()</td></tr> <tr><td align="left">+setGraphId()</td></tr> <tr><td align="left">+renderClass()</td></tr> <tr><td align="left">+renderNamespace()</td></tr> <tr><td align="left">+render()</td></tr> <tr><td align="left">#renderEdges()</td></tr> <tr><td align="left">#formatLine()</td></tr> <tr><td align="left">#writeObjectElement()</td></tr> <tr><td align="left">#writeObjectInheritance()</td></tr> <tr><td align="left">#writeObjectInterfaces()</td></tr> <tr><td align="left">#writeConstantElements()</td></tr> <tr><td align="left">#writePropertyElements()</td></tr> <tr><td align="left">#writeMethodElements()</td></tr> <tr><td align="left">#<i>pushObject</i>()</td></tr> <tr><td align="left">#<i>pushEdge</i>()</td></tr> <tr><td align="left">#formatClassStereotype()</td></tr> <tr><td align="left">-reset()</td></tr> </table></td></tr> </table> >]; "Bartlett\\UmlWriter\\Processor\\GraphvizProcessor" [label=< <table border="0" cellborder="1" cellspacing="0"> <tr><td align="center"><< <font color="black"><i>class</i></font> >><br/><b>GraphvizProcessor</b></td></tr> <tr><td><table border="0" cellspacing="0" cellpadding="2"> <tr><td align="left"># namespaceSeparator</td></tr> </table></td></tr> <tr><td><table border="0" cellspacing="0" cellpadding="2"> <tr><td align="left">#renderObjects()</td></tr> <tr><td align="left">#renderEdges()</td></tr> <tr><td align="left">#writeGraphHeader()</td></tr> <tr><td align="left">#writeGraphFooter()</td></tr> <tr><td align="left">#pushObject()</td></tr> <tr><td align="left">#pushEdge()</td></tr> <tr><td align="left">-attributes()</td></tr> </table></td></tr> </table> >]; "Bartlett\\UmlWriter\\Processor\\ProcessorInterface" [label=< <table border="0" cellborder="1" cellspacing="0"> <tr><td align="center"><< <font color="black"><i>interface</i></font> >><br/><b>ProcessorInterface</b></td></tr> <tr><td><table border="0" cellspacing="0" cellpadding="2"> <tr><td align="left">+ GLOBAL_NAMESPACE</td></tr> </table></td></tr> <tr><td><table border="0" cellspacing="0" cellpadding="2"> <tr><td align="left">+renderClass()</td></tr> <tr><td align="left">+renderNamespace()</td></tr> <tr><td align="left">+render()</td></tr> </table></td></tr> </table> >]; "Bartlett\\UmlWriter\\Processor\\PlantUMLProcessor" [label=< <table border="0" cellborder="1" cellspacing="0"> <tr><td align="center"><< <font color="black"><i>class</i></font> >><br/><b>PlantUMLProcessor</b></td></tr> <tr><td><table border="0" cellspacing="0" cellpadding="2"> <tr><td align="left"># namespaceSeparator</td></tr> </table></td></tr> <tr><td><table border="0" cellspacing="0" cellpadding="2"> <tr><td align="left">#renderObjects()</td></tr> <tr><td align="left">#renderEdges()</td></tr> <tr><td align="left">#writeGraphHeader()</td></tr> <tr><td align="left">#writeGraphFooter()</td></tr> <tr><td align="left">#pushObject()</td></tr> <tr><td align="left">#pushEdge()</td></tr> </table></td></tr> </table> >]; } "Bartlett\\UmlWriter\\Processor\\GraphvizProcessor" -> "Bartlett\\UmlWriter\\Processor\\AbstractProcessor"; "Bartlett\\UmlWriter\\Processor\\GraphvizProcessor" -> "Bartlett\\UmlWriter\\Processor\\ProcessorInterface" [arrowhead="empty", style="dashed"]; "Bartlett\\UmlWriter\\Processor\\PlantUMLProcessor" -> "Bartlett\\UmlWriter\\Processor\\AbstractProcessor"; "Bartlett\\UmlWriter\\Processor\\PlantUMLProcessor" -> "Bartlett\\UmlWriter\\Processor\\ProcessorInterface" [arrowhead="empty", style="dashed"]; } That may render something like |
diagram:render:class |
Generate diagram statements of a single class. $ umlwriter diagram:render:class --processor=graphviz vendor/bartlett/php-reflect/src Bartlett\Reflect digraph G { overlap = false; node [fontname="Verdana", fontsize="8", shape="none", margin="0", fillcolor="#FEFECE", style="filled"]; edge [fontname="Verdana", fontsize="8"]; subgraph cluster_0 { label="Bartlett"; "Bartlett\\Reflect" [label=< <table border="0" cellborder="1" cellspacing="0"> <tr><td align="center"><< <font color="black"><i>class</i></font> >><br/><b>Reflect</b></td></tr> <tr><td><table border="0" cellspacing="0" cellpadding="2"> <tr><td align="left">- analysers</td></tr> <tr><td align="left">- dataSourceId</td></tr> </table></td></tr> <tr><td><table border="0" cellspacing="0" cellpadding="2"> <tr><td align="left">+__construct()</td></tr> <tr><td align="left">+addAnalyser()</td></tr> <tr><td align="left">+getAnalysers()</td></tr> <tr><td align="left">+setDataSourceId()</td></tr> <tr><td align="left">+getDataSourceId()</td></tr> <tr><td align="left">+parse()</td></tr> </table></td></tr> </table> >]; } subgraph cluster_1 { label="Bartlett\\Reflect\\Event"; "Bartlett\\Reflect\\Event\\AbstractDispatcher" [label=< <table border="0" cellborder="1" cellspacing="0"> <tr><td align="center"><< <font color="black"><i>class</i></font> >><br/><b>AbstractDispatcher</b></td></tr> <tr><td><table border="0" cellspacing="0" cellpadding="2"> <tr><td align="left"># eventDispatcher</td></tr> </table></td></tr> <tr><td><table border="0" cellspacing="0" cellpadding="2"> <tr><td align="left">+setEventDispatcher()</td></tr> <tr><td align="left">+getEventDispatcher()</td></tr> <tr><td align="left">+dispatch()</td></tr> <tr><td align="left">+addSubscriber()</td></tr> </table></td></tr> </table> >]; "Bartlett\\Reflect\\Event\\DispatcherInterface" [label=< <table border="0" cellborder="1" cellspacing="0"> <tr><td align="center"><< <font color="black"><i>interface</i></font> >><br/><b>DispatcherInterface</b></td></tr> <tr><td> </td></tr> <tr><td><table border="0" cellspacing="0" cellpadding="2"> <tr><td align="left">+setEventDispatcher()</td></tr> <tr><td align="left">+getEventDispatcher()</td></tr> <tr><td align="left">+dispatch()</td></tr> <tr><td align="left">+addSubscriber()</td></tr> </table></td></tr> </table> >]; } "Bartlett\\Reflect\\Event\\AbstractDispatcher" -> "Bartlett\\Reflect\\Event\\DispatcherInterface" [arrowhead="empty", style="dashed"]; "Bartlett\\Reflect" -> "Bartlett\\Reflect\\Event\\AbstractDispatcher"; } That may render something like |
diagram:render:namespace |
Generate diagram statements of a single namespace. $ umlwriter diagram:render:namespace --processor=plantuml vendor/bartlett/php-reflect/src Bartlett\Reflect\Plugin\Notifier @startuml namespace Bartlett.Reflect.Plugin.Notifier { class GrowlNotifier << class >> { -growl -format -- +__construct() +setMessageFormat() +getMessageFormat() +notify() } interface NotifierInterface << interface >> { +setMessageFormat() +getMessageFormat() +notify() } } Bartlett.Reflect.Plugin.Notifier.GrowlNotifier ..|> Bartlett.Reflect.Plugin.Notifier.NotifierInterface @enduml That may render something like |
Let’s review what we’ve learned about the command-line interface :
Each processor is a specialized version of a graphical engine. UmlWriter version 1.0.0 is able to render only two diagram syntaxes :
But you are free to make your own. Here is the class diagram of processors architecture built with PlantUML processor
How To Build It. With the CLI mode, use the umlwriter command. $ umlwriter diagram:render:namespace --processor=plantuml /path/to/umlwriter Bartlett\UmlWriter\Processor Output return the PlantUML diagram syntax, that you may redirect directly to a file Then build a $ java -jar plantuml.jar -Tpng /path/to/puml_file -o /path/to/ouput/dir |
Any new processor must implement the Bartlett\UmlWriter\Processor\ProcessorInterface
interface.
And to avoid to implement again and again the same methods, you should used
the abstract Bartlett\UmlWriter\Processor\AbstractProcessor
class, that will do
the job for you.
There are three methods to implement :
renderClass()
that is in charge of return diagram syntax of a single class and its direct dependencies.
renderNamespace()
that is in charge of return diagram syntax of a single namespace and all its objects.
render()
that is in charge of return diagram syntax of all namespaces and objects.
There are additional protected methods available in the abstract
Bartlett\UmlWriter\Processor\AbstractProcessor
class.
renderEdges()
that is in charge of building all links between objects (class, interface, trait)
formatLine()
that may format line with a left indentation.
writeObjectElement()
that render details of each object (class, interface, trait) in a namespace
writeObjectInheritance()
that render the class or interface parent.
writeObjectInterfaces()
that render all interfaces implemented by a class
writePropertyElements()
that render all properties of a class
writeMethodElements()
that render all methods of any objects (class, interface, trait)
There are two abstract methods you should implement :
pushObject()
to render an object with all details (attributes, operations)
pushEdge()
to render links (inheritances, implements) between objects
Other specialized methods that each processor must implement :
writeGraphHeader()
to render header of the main graph
writeGraphFooter()
to render footer of the main graph
Each reflector is a specialized version of a compatible reverse-engine. UmlWriter version 1.0.0 is able to use only two engines :
Here is the class diagram of reflectors architecture (built with default PlantUML processor)
Any new reflector must implement the Bartlett\UmlWriter\Reflector\ReflectorInterface
interface.