While it does not replace good judgement and programming practice completely, it can be interesting to perform regular code quality analyses to make sure that your teams (and students) are writing good PHP code. This is a small guide on how to install them in macOS and how to use them to automatically produce metrics for all code repositories in a folder.

This is intended as a very short guide on how to perform static code analysis on projects that are not under Git source code control, with minimal configuration and without relying on a CI/CD solution. For those other cases, I recommend Codacy and Travis.CI. I have been using these myself for years and I think they are great!

Installing prerequisites

Before installing the tools themselves, you may have to install some supporting software in your Mac. If you already have these installed, please move on to the tool installation section.

Homebrew

First install Homebrew, the missing package manager for macOS.

Install PHP Composer

 1 brew install composer

 1 2 3 joaorocha at modo in ~ $composer --version Composer version 1.9.1 2019-11-01 17:20:17 Installing the tools We are going to target 3 types of analyses: Detection of duplicates, size and complexity of code without considering OOP metrics, and detailed analysis of OOP structure in PHP. Detecting Copy-Pastes (duplicate code) An interesting tool to detect copy pasted code is PHP Copy/Paste Detector (PHPCPD). Let’s install it:  1 composer global require sebastian/phpcpd And run it:  1 phpcpd --fuzzy /folder/you/want/to/analyse Getting code quality metrics (Generic) phploc is a tool for quickly measuring the size and analyzing the structure of a PHP project. Let’s install it:  1 composer global require phploc/phploc And run it:  1 phploc /path/to/your/sources Getting code quality metrics (OOP) Another interesting open-source tool is PHPMetrics. It produces some nice HTML reports, with support for color blind people too! According to the authors, PhpMetrics is intended for projects with usages of packages, namespaces, classes, interfaces, and other structures like that.. Let’s install it:  1 composer global require 'phpmetrics/phpmetrics' The composer executables may not be added to your path by default. Let’s fix that by adding the following line to your ~/.zshrc file (if you use zsh) or ~/.bash_profile (if you use bash):  1 export PATH=$PATH:~/.composer/vendor/bin

And run the command:

 1 phpmetrics --report-html=myreport.html /path/of/your/sources

Putting it all together

Here is a script to perform all the analyses shown before, and place the results in a neat folder called output beside your source folders. For every folder, the script will run these utilities and produce a subfolder with the results of every single one.

Create a new file called evaluate.sh in the folder that contains the subfolders that you want to analyse and copy and paste the following lines.

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #!/usr/bin/env bash NUMBER_OF_LINES_CONSIDERED_COPY_PASTE=2 MIN_TOKENS_CONSIDERED_COPY_PASTE=15 OUTPUT_DIR=$(pwd)/output # exclude hidden directories shopt -s dotglob # delete existing results if they exist if [[ -d "$OUTPUT_DIR" ]]; then rm -rf "$OUTPUT_DIR" fi # for every folder for subfolder in */ ; do echo "####################################################" echo "Analysing$subfolder ..." echo "####################################################" SUBFOLDER_NAME=$(basename "$subfolder") RESULTS_SUBDIR="$OUTPUT_DIR/$SUBFOLDER_NAME" if [[ ! -d "$RESULTS_SUBDIR" ]]; then mkdir -p "$RESULTS_SUBDIR" fi # run phpcpd phpcpd --min-tokens="$MIN_TOKENS_CONSIDERED_COPY_PASTE" --min-lines="$NUMBER_OF_LINES_CONSIDERED_COPY_PASTE" --fuzzy "$subfolder" > "$RESULTS_SUBDIR/phpcpd.txt" # run phploc phploc "$subfolder" > "$RESULTS_SUBDIR/phploc.txt" #run phpmetrics phpmetrics --report-html="$RESULTS_SUBDIR/phpmetrics" "$subfolder" done

To get the results, cd to the previously mentioned folder, and make the script executable with chmod +x evaluate.sh and run it using ./evaluate.sh.

Results

You will get something like this.

Copy-paste detection

phpcpd 4.1.0 by Sebastian Bergmann.

No clones found.

Time: 35 ms, Memory: 4.00MB
phploc 5.0.0 by Sebastian Bergmann.

Size
Lines of Code (LOC)                             1948
Comment Lines of Code (CLOC)                      43 (2.21%)
Non-Comment Lines of Code (NCLOC)               1905 (97.79%)
Logical Lines of Code (LLOC)                     627 (32.19%)
Classes                                          0 (0.00%)
Average Class Length                           0
Minimum Class Length                         0
Maximum Class Length                         0
Average Method Length                          0
Minimum Method Length                        0
Maximum Method Length                        0
Functions                                      318 (50.72%)
Average Function Length                        6
Not in classes or functions                    309 (49.28%)

Cyclomatic Complexity
Average Complexity per LLOC                     0.22
Average Complexity per Class                    0.00
Minimum Class Complexity                      0.00
Maximum Class Complexity                      0.00
Average Complexity per Method                   0.00
Minimum Method Complexity                     0.00
Maximum Method Complexity                     0.00

Dependencies
Global Accesses                                  166
Global Constants                                 0 (0.00%)
Global Variables                                50 (30.12%)
Super-Global Variables                         116 (69.88%)
Attribute Accesses                                 0
Non-Static                                       0 (0.00%)
Static                                           0 (0.00%)
Method Calls                                     191
Non-Static                                     191 (100.00%)
Static                                           0 (0.00%)

Structure
Namespaces                                         0
Interfaces                                         0
Traits                                             0
Classes                                            0
Abstract Classes                                 0 (0.00%)
Concrete Classes                                 0 (0.00%)
Methods                                            0
Scope
Non-Static Methods                             0 (0.00%)
Static Methods                                 0 (0.00%)
Visibility
Public Methods                                 0 (0.00%)
Non-Public Methods                             0 (0.00%)
Functions                                         53
Named Functions                                 53 (100.00%)
Anonymous Functions                              0 (0.00%)
Constants                                          0
Global Constants                                 0 (0.00%)
Class Constants                                  0 (0.00%)