Rule S117: False positives on PHP 8 constructor property promotion

Since PHP 8.0, constructor property promotion allows declaring class properties directly in the constructor signature:

public function __construct(
    protected EntityTypeManagerInterface $entityTypeManager,
) {}

This is syntactic sugar for:

protected EntityTypeManagerInterface $entityTypeManager;

public function __construct(
    EntityTypeManagerInterface $entityTypeManager,
) {
    $this->entityTypeManager = $entityTypeManager;
}

Promoted parameters are class fields, not regular function parameters. However, rule S117 treats them as regular parameters and flags them when they don’t match the parameter naming convention.

This produces false positives when the project uses a different naming convention for properties and parameters. For example, in Drupal:

  • Class properties: camelCase ($entityTypeManager)

  • Local variables and function parameters: snake_case ($entity_type_manager)

With S117 configured for snake_case (^[a-z][a-z0-9_]*$), every promoted property using the correct camelCase convention is flagged.

Noncompliant Code (false positive)

With S117 configured for snake_case parameters:

class NodeAccessHandler {

    public function __construct(
        protected EntityTypeManagerInterface $entityTypeManager, // S117 flags this — FALSE POSITIVE
        protected AccountProxyInterface $currentUser, // S117 flags this — FALSE POSITIVE
    ) {}

    public function checkAccess(NodeInterface $node, string $operation): AccessResult {
        $access_records = $this->entityTypeManager->getStorage('node_access')->loadMultiple();
        // ...
    }
}

$entityTypeManager and $currentUser are class properties, not parameters. Their camelCase naming is correct per the property convention. S117 should not flag them.

Compliant Code

The code above is compliant — no changes needed. S117 should simply skip promoted properties.

Mixed constructor (promoted and non-promoted parameters)

class MyService {

    public function __construct(
        // Promoted → class property → S117 should NOT check this
        protected EntityTypeManagerInterface $entityTypeManager,
        // NOT promoted → regular parameter → S117 SHOULD check this
        string $module_name,
    ) {}
}

S117 should only validate $module_name. $entityTypeManager should be excluded from S117 because it is a promoted property (rule S116 “Field names should comply with a naming convention” is the appropriate rule for it).

Exceptions

S117 should exclude constructor parameters that have any of:

  • A visibility modifier: public, protected, or private

  • The readonly modifier

  • Any combination (e.g., public readonly)

These keywords mark a parameter as promoted (i.e., a class property), and the parameter naming convention should not apply to them.

External References

  • PHP RFC: Constructor Property Promotion (PHP 8.0)

  • PHP Manual: Constructor promotion

  • Drupal coding standards: Naming conventions — snake_case for variables/parameters, camelCase for class properties

  • Drupal core uses promoted properties with camelCase extensively since Drupal 10

  • Symfony and Laravel also widely use constructor promotion with camelCase

Type

Bug — S117 raises false positives on a standard PHP 8.0+ language feature widely adopted since 2020.

Hi,

Thanks for this thorough report! I just need your context. I.e. are you on SonarQube Cloud? SonarQube for IDE (flavor and version)? SonarQube self-managed (flavor and version)? (I need to make sure you’re in a current version before I flag this for the developers. :grin:)

 
Thx,
Ann

SonarQube Cloud.

Hi,

Thanks! This is flagged for the language experts.

 
Ann

Hi @mably,

Thanks for the thorough report — you’re right, this is should be considered a false-positive. S117 should skip promoted properties and only check regular parameters. I’ve logged it internally and will get it fixed soon.

Thanks @Karim_El_Ouerghemmi!