Skip to content

1. Introduction

Marco Muths edited this page Mar 17, 2017 · 3 revisions

Preface

PhpDependencyAnalysis is an extendable static code analysis for object-oriented PHP-Projects (>= 5.6) to generate a graph from abstract datatypes (Classes, Interfaces and Traits) based on namespaces.

It can create Call-Graphs, Inheritance-Graphs and Usage-Graphs (Call + Inheritance). Dependencies can be aggregated to custom levels, such as package-level or class-level.

Thus it illustrates dependencies and can detect violations against a reference architecture according to SoC (Separation of Concerns), LoD (Law of Demeter) and ADP (Acyclic Dependencies Principle).

Why I need this?

Huge projects should have an architecture definition, which declares communication channels (dependencies) between different services, packages, modules, components or layers. Those definitions are helpful to tackle complexities in huge projects to improve the maintainabilty.

For instance Package A is permitted to communicate with Package B and C. In case of Package A has a dependency to Package D, you have a violation.

Or an Application is separated in Services and each Service encapsulate their Persistence Layer. In this case amongst others an Application Controller is not permitted to communicate to the Persistence Layer directly.

Cycle dependencies have to be avoided to improve the interchangeability. For instance Layer A has a dependency to Layer B, Layer B has a dependecy to Layer C and Layer C has a dependency to Layer A.

Without detecting and tackling those violations huge projects often emerge to Big Ball of Mud structures.

That's why you you should use PhpDependencyAnalysis.

How it works

It parses all found PHP-files to extract all containing ADT's (Abstract Datatypes). An ADT can be an interface, a trait or a class (concrete, abstract, anonymous or final).

After that each ADT is converted to an abstract syntax tree and all nodes of this tree will be traversed. Comments like PHPDocBlocks are also abstracted as a node. Each node is visited by registered collectors (visitor objects) while traversing. A collector inspects this node to collect a dependency to current ADT.

A dependency can be type of inheritance or type of call. Inheritance is defined by implementation, class-extending or a trait-use. Call is defined by a method parameter, by a method return-value or by an instance creation. A dependency is identified by their FQCN (Fully-Qualified Class Name). Those namespaces are sliceable to their namespace parts. In this way an aggregation of dependencies to a specific level is possible.

In the end it creates a directed graph of all ADTs (vertices) and their dependecies (edges). Cycles (detected automaticly) and violations detected by your defined reference architecture are highlighted in red.

Goals

In most cases huge projects hold a very huge dependency graph, which is not easy to visit. That's why PhpDependencyAnalysis provides a high customizing level to change the scope for inspections. For instance you can filter namespaces to have a view on package level only or you can parse a specific package or a specific PHP file. You can also exclude found namespaces from inspection.

But the main goal is verifying a given architecture against a defined one.

See Examples-Chapter and Configuration-Chapter for more details.

Most PHP-Projects are using IoC-Containers for Dependecy-Injection, like ZF2-ServiceManager or Pimple. All of them provide objects by a string representation which are not resolvable to dependencies up front. For this reason this tool is extendable by adding user-defined plugins to meet this requirement.

Another good idea for an user-defined plugin can be a visitor to detect database tables as a dependency by parsing string nodes.

See Plugins-Chapter for more details.

Clone this wiki locally