TIL: Why PHPMD and SonarCloud don’t always agree
Here’s a good one for the “quirks of tooling” file. We set up both SonarCloud and PHPMD to enforce a limit on the number of public methods in our classes. Same limit, same rules... or so we thought. But then SonarCloud flagged way more issues than PHPMD, and we were left scratching our heads. Naturally, we dove in to figure out what was going on. Spoiler alert: it wasn’t a bug—it was a feature. PHPMD Has a Secret List of “Favorite” Methods After some investigation, we discovered that PHPMD doesn’t count every method by default. Instead, it skips certain methods based on their names. The documentation claims that only get and set methods are ignored by the TooManyMethods rule. But wait! The actual default behavior is even sneakier. Here’s the real regex pattern PHPMD uses by default: So in reality, PHPMD also ignores methods starting with is, has, and with. This explains why SonarCloud was flagging more issues—SonarCloud doesn’t play favorites. Fixing the Mismatch We decided we didn’t want any special treatment—every method should count, no matter what it starts with. The obvious first step was to leave the ignorepattern empty. But PHPMD didn’t seem to understand “empty” the way we expected, so that didn’t work. To get PHPMD to count all methods, we had to explicitly override the default pattern. Here’s the configuration we landed on: The regex (!)i essentially tells PHPMD: “Don’t ignore anything. Count every single method.” Now, PHPMD and SonarCloud are on the same page, and our rule enforcement is consistent. What We Learned PHPMD is full of surprises: Its default rules skip over methods starting with certain prefixes, and the documentation doesn’t tell the whole story. Don’t assume tools behave the same way: Just because two tools seem to check for the same thing doesn’t mean their definitions match. Regex saves the day: To make PHPMD truly count everything, use a pattern like (!)i to ensure no methods are skipped. A Fun Thought Maybe PHPMD’s on to something. If we ignored all tasks starting with “fold” or “clean,” wouldn’t life seem a whole lot easier? Unfortunately, our code doesn’t work that way, so neither can we.

Here’s a good one for the “quirks of tooling” file. We set up both SonarCloud and PHPMD to enforce a limit on the number of public methods in our classes. Same limit, same rules... or so we thought. But then SonarCloud flagged way more issues than PHPMD, and we were left scratching our heads. Naturally, we dove in to figure out what was going on. Spoiler alert: it wasn’t a bug—it was a feature.
PHPMD Has a Secret List of “Favorite” Methods
After some investigation, we discovered that PHPMD doesn’t count every method by default. Instead, it skips certain methods based on their names. The documentation claims that only get
and set
methods are ignored by the TooManyMethods
rule.
But wait! The actual default behavior is even sneakier. Here’s the real regex pattern PHPMD uses by default:
name="ignorepattern" value="(^(set|get|is|has|with))i"/>
So in reality, PHPMD also ignores methods starting with is
, has
, and with
. This explains why SonarCloud was flagging more issues—SonarCloud doesn’t play favorites.
Fixing the Mismatch
We decided we didn’t want any special treatment—every method should count, no matter what it starts with. The obvious first step was to leave the ignorepattern
empty. But PHPMD didn’t seem to understand “empty” the way we expected, so that didn’t work.
To get PHPMD to count all methods, we had to explicitly override the default pattern. Here’s the configuration we landed on:
ref="rulesets/codesize.xml/TooManyMethods" message="The {0} {1} has {2}. Consider refactoring {1} to keep the number of methods under {3}.">
name="maxmethods" value="20"/>
name="ignorepattern" value="(!)i"/>
ref="rulesets/codesize.xml/TooManyPublicMethods">
name="maxmethods" value="20"/>
name="ignorepattern" value="(!)i"/>
The regex (!)i
essentially tells PHPMD: “Don’t ignore anything. Count every single method.” Now, PHPMD and SonarCloud are on the same page, and our rule enforcement is consistent.
What We Learned
- PHPMD is full of surprises: Its default rules skip over methods starting with certain prefixes, and the documentation doesn’t tell the whole story.
- Don’t assume tools behave the same way: Just because two tools seem to check for the same thing doesn’t mean their definitions match.
-
Regex saves the day: To make PHPMD truly count everything, use a pattern like
(!)i
to ensure no methods are skipped.
A Fun Thought
Maybe PHPMD’s on to something. If we ignored all tasks starting with “fold” or “clean,” wouldn’t life seem a whole lot easier? Unfortunately, our code doesn’t work that way, so neither can we.