To check if we are producing clean and tidy code, there is a tool available that can help us.
This tool is called PHPMD, which stands for “PHP Mess Detector”.
As the name implies the tool tries to detect messy code and warns us about it. It does so based on sets of rules. We will go over them one by one in this document, but the most up-to-date version can be found here: https://phpmd.org/rules/index.html.
The Clean Code ruleset contains rules that enforce a clean code base. This includes rules from SOLID and Object Calisthenics.
BooleanArgumentFlag
A boolean flag argument is a reliable indicator for a violation of the Single Responsibility Principle (SRP). You can fix this problem by extracting the logic in the boolean flag into its own class or method.
ElseExpression
An if expression with an else branch is never necessary. You can rewrite the conditions in a way that the else is not necessary and the code becomes simpler to read. To achieve this use early return statements. To achieve this you may need to split the code it several smaller methods. For very simple assignments you could also use the ternary operations.
StaticAccess
Static access causes unexchangeable dependencies to other classes and leads to hard to test code. Avoid using static access at all costs and instead inject dependencies through the constructor.
The Code Size Ruleset contains a collection of rules that find code size related problems.
CyclomaticComplexity
Complexity is determined by the number of decision points in a method plus one for the method entry. The decision points are 'if', 'while', 'for', and 'case labels'. Generally, 1-4 is low complexity, 5-7 indicates moderate complexity, 8-10 is high complexity, and 11+ is very high complexity.
NPathComplexity
The NPath complexity of a method is the number of acyclic execution paths through that method. A threshold of 200 is generally considered the point where measures should be taken to reduce complexity.
ExcessiveMethodLength
Violations of this rule usually indicate that the method is doing too much. Try to reduce the method size by creating helper methods and removing any copy/pasted code.
ExcessiveClassLength
Long class files are indications that the class may be trying to do too much. Try to break it down, and reduce the size to something manageable.
ExcessiveParameterList
Long parameter lists can indicate that a new object should be created to wrap the numerous parameters. Basically, try to group the parameters together.
ExcessivePublicCount
A large number of public methods and attributes declared in a class can indicate the class may need to be broken up as increased effort will be required to thoroughly test it.
TooManyFields
Classes that have too many fields could be redesigned to have fewer fields, possibly through some nested object grouping of some of the information. For example, a class with city/state/zip fields could instead have one Address field.
TooManyMethods
A class with too many methods is probably a good suspect for refactoring, in order to reduce its complexity and find a way to have more fine grained objects. By default it ignores methods starting with 'get' or 'set'. The default was changed from 10 to 25 in PHPMD 2.3.
TooManyPublicMethods
A class with too many public methods is probably a good suspect for refactoring, in order to reduce its complexity and find a way to have more fine grained objects. By default it ignores methods starting with 'get' or 'set'.
ExcessiveClassComplexity
The Weighted Method Count (WMC) of a class is a good indicator of how much time and effort is required to modify and maintain this class. The WMC metric is defined as the sum of complexities of all methods declared in a class. A large number of methods also means that this class has a greater potential impact on derived classes.
This ruleset contains a collection of controversial rules.
Superglobals
Accessing a super-global variable directly is considered a bad practice. These variables should be encapsulated in objects that are provided by a framework, for instance.
CamelCaseClassName
It is considered best practice to use the CamelCase notation to name classes.
CamelCasePropertyName
It is considered best practice to use the camelCase notation to name attributes.
CamelCaseMethodName
It is considered best practice to use the camelCase notation to name methods.
CamelCaseParameterName
It is considered best practice to use the camelCase notation to name parameters.
CamelCaseVariableName
It is considered best practice to use the camelCase notation to name variables.
The Design Ruleset contains a collection of rules that find software design related problems.
ExitExpression
An exit-expression within regular code is untestable and therefore it should be avoided. Consider to move the exit-expression into some kind of startup script where an error/exception code is returned to the calling environment.
EvalExpression
An eval-expression is untestable, a security risk and bad practice. Therefore it should be avoided. Consider to replace the eval-expression with regular code.
GotoStatement
Goto makes code harder to read and it is nearly impossible to understand the control flow of an application that uses this language construct. Therefore it should be avoided. Consider to replace Goto with regular control structures and separate methods/function, which are easier to read.
NumberOfChildren
A class with an excessive number of children is an indicator for an unbalanced class hierarchy. You should consider to refactor this class hierarchy.
DepthOfInheritance
A class with many parents is an indicator for an unbalanced and wrong class hierarchy. You should consider to refactor this class hierarchy.
CouplingBetweenObjects
A class with too many dependencies has negative impacts on several quality aspects of a class. This includes quality criteria like stability, maintainability and understandability.
DevelopmentCodeFragment
Functions like var_dump(), print_r() etc. are normally only used during development and therefore such calls in production code are a good indicator that they were just forgotten.
The Naming Ruleset contains a collection of rules about names - too long, too short, and so forth.
ShortVariable
Detects when a field, local, or parameter has a very short name.
LongVariable
Detects when a field, formal or local variable is declared with a long name.
ShortMethodName
Detects when very short method names are used.
ConstructorWithNameAsEnclosingClass
A constructor method should not have the same name as the enclosing class, consider to use the PHP 5 __construct method.
ConstantNamingConventions
Class/Interface constant names should always be defined in uppercase.
BooleanGetMethodName
Looks for methods named 'getX()' with 'boolean' as the return type. The convention is to name these methods 'isX()' or 'hasX()'.
The Unused Code Ruleset contains a collection of rules that find unused code.
UnusedPrivateField
Detects when a private field is declared and/or assigned a value, but not used.
UnusedLocalVariable
Detects when a local variable is declared and/or assigned, but not used.
UnusedPrivateMethod
Unused Private Method detects when a private method is declared but is unused.
UnusedFormalParameter
Avoid passing parameters to methods or constructors and then not using those parameters.
PHP Mess Detector can be installed using composer with the following command:
$ composer require phpmd/phpmd --dev
This will install the tool in the vendor folder of your project.
You can then execute it with the following command:
$ vendor/bin/phpmd path/to/php/files text \
cleancode,codesize,controversial,design,naming,unusedcode
This will run all of the available rulesets on all php files found in the path you provided and produce output in the “text” format (you can also choose xml or html).