1. Rules

1.1. Introduction

Exakat provides unique 1383 rules to detect BUGS, CODE SMELLS, SECURITY OR QUALITY ISSUES in your PHP code.

Each rule is documented with code example to allow you to remediate your code. If you want to automate remediation, ours cobblers can are there to fix the issues in your code for your.

1.2. List of Rules

1.2.1. Ambiguous Array Index

Indexes should not be defined with different types than int or string.

Array indices only accept integers and strings, so any other type of literal is reported. In fact, null is turned into an empty string, booleans are turned into an integer, and real numbers are truncated (not rounded).

<?php

$x = [ 1  => 1,
      '1' => 2,
      1.0 => 3,
      true => 4];
// $x only contains one element : 1 => 4

// Still wrong, immediate typecast to 1
$x[1.0]  = 5;
$x[true] = 6;

?>

They are indeed distinct, but may lead to confusion.

See also array.

1.2.1.1. Suggestions

  • Only use string or integer as key for an array.
  • Use transtyping operator (string) and (int) to make sure of the type

1.2.1.2. Specs

Short name Arrays/AmbiguousKeys
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High
Examples PrestaShop, Mautic

1.2.2. Array() / [ ] Consistence

array() or [ ] is the favorite.

array() and [ ] have the same functional use.

The analyzed code has less than 10% of one of them : for consistency reasons, it is recommended to make them all the same.

It happens that array() or [] are used depending on coding style and files. One file may be consistently using array(), while the others are all using [].

<?php

$a = array(1, 2);
$b = array(array(3, 4), array(5, 6));
$c = array(array(array(7, 8), array(9, 10)), array(11, 12), array(13, 14)));

// be consistent
$d = [1, 3];
?>

The only drawback to use [] over array() is backward incompatibility.

1.2.2.1. Suggestions

  • Use one syntax consistently.
Name Default Type Description
array_ratio 10 integer Percentage of arrays in one of the syntaxes, to trigger the other syntax as a violation.

1.2.2.2. Specs

Short name Arrays/ArrayBracketConsistence
Rulesets none
Exakt since 0.8.9
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.3. Array Index

List of all indexes used in arrays.
<?php

// Index
$x['index'] = 1;

// in array creation
$a = array('index2' => 1);
$a2 = ['index3' => 2];

?>

1.2.3.1. Specs

Short name Arrays/Arrayindex
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Instant (5 mins)
Precision Very high

1.2.4. Short Syntax For Arrays

Arrays written with the new short syntax.

PHP 5.4 introduced the new short syntax, with square brackets. The previous syntax, based on the array() keyword is still available.

<?php

// All PHP versions array
$a = array(1, 2, 3);

// PHP 5.4+ arrays
$a = [1, 2, 3];

?>

See also Array.

1.2.4.1. Specs

Short name Arrays/ArrayNSUsage
Rulesets CE, CompatibilityPHP53
Exakt since 0.8.4
Php Version All
Severity Critical
Time To Fix Quick (30 mins)
Precision High

1.2.5. Empty Final Element

The array() construct allows for the empty last element.

By putting an element on each line, and adding the final comma, it is possible to reduce the size of the diff when comparing code with the previous version.

<?php

// Array definition with final empty element
$array = [1,
          2,
          3,
          ];

// This array definition has only one line of diff with the previous array : the line with '4,'
$array = [1,
          2,
          3,
          4,
          ];

// This array definition is totally different from the first array :
$array = [1, 2, 3, 4];

?>

See also Array, Zend Framework Coding Standard and How clean is your code? How clean are your diffs?.

1.2.5.1. Specs

Short name Arrays/EmptyFinal
Rulesets none
Exakt since 0.11.0
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.6. Empty Slots In Arrays

PHP tolerates the last element of an array to be empty.
<?php
    $a = array( 1, 2, 3, );
    $b =      [ 4, 5, ];
?>

1.2.6.1. Specs

Short name Arrays/EmptySlots
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Instant (5 mins)
Precision High

1.2.7. Getting Last Element

Getting the last element of an array relies on array_key_last().

array_key_last() was added in PHP 7.3. Before that,

<?php

$array = ['a' => 1, 'b' => 2, 'c' => 3];

// Best solutions, by far
$last = $array[array_key_last($array)];

// Best solutions, just as fast as each other
$last = $array[count($array) - 1];
$last = end($array);

// Bad solutions

// popping, but restoring the value.
$last = array_pop($array);
$array[] = $last;

// array_unshift would be even worse

// reversing array
$last = array_reverse($array)[0];

// slicing the array
$last = array_slice($array, -1)[0]',
$last = current(array_slice($array, -1));
);

?>

1.2.7.1. Suggestions

  • Use PHP native function : array_key_last(), when using PHP 7.4 and later
  • Use PHP native function : array_pop()
  • Organise the code to put the last element in the first position (array_unshift() instead of append operator [])

1.2.7.2. Specs

Short name Arrays/GettingLastElement
Rulesets Performances
Exakt since 0.9.0
Php Version All
Severity Minor
Time To Fix Instant (5 mins)
Precision High
Examples Thelia

1.2.8. Mass Creation Of Arrays

Literal creation of an array, by assigning a lot of index.
<?php

$row['name'] = $name;
$row['last'] = $last;
$row['address'] = $address;

?>

1.2.8.1. Specs

Short name Arrays/MassCreation
Rulesets none
Exakt since 1.1.8
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.9. Mistaken Concatenation

A unexpected structure is built for initialization. It may be a typo that creates an unwanted expression.
<?php

// This 'cd' is unexpected. Isn't it 'c', 'd' ?
$array = array('a', 'b', 'c'. 'd');
$array = array('a', 'b', 'c', 'd');

// This 4.5 is unexpected. Isn't it 4, 5 ?
$array = array(1, 2, 3, 4.5);
$array = array(1, 2, 3, 4, 5);

?>

1.2.9.1. Specs

Short name Arrays/MistakenConcatenation
Rulesets none
Exakt since 1.0.8
Php Version All
Severity Major
Time To Fix Instant (5 mins)
Precision High

1.2.10. Mixed Keys Arrays

Avoid mixing constants and literals in array keys.

When defining default values in arrays, it is recommended to avoid mixing constants and literals, as PHP may mistake them and overwrite the previous with the latter.

Either switch to a newer version of PHP (5.5 or newer), or make sure the resulting array hold the expected data. If not, reorder the definitions.

<?php

const ONE = 1;

$a = [ 1   => 2,
       ONE => 3];

?>

1.2.10.1. Suggestions

  • Use only literals or constants when building the array

1.2.10.2. Specs

Short name Arrays/MixedKeys
Rulesets CompatibilityPHP53, CompatibilityPHP54
Exakt since 0.8.4
Php Version 5.6+
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.11. Multidimensional Arrays

Simply, arrays of arrays.
<?php
    $x[1][2] = $x[2][3][4];

?>

See also Type array and Using Multidimensional Arrays in PHP.

1.2.11.1. Specs

Short name Arrays/Multidimensional
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.12. Multiple Index Definition

Indexes that are defined multiple times in the same array.
<?php
    // Multiple identical keys
    $x = array(1 => 2,
               2 => 3,
               1 => 3);

    // Multiple identical keys (sneaky version)
    $x = array(1 => 2,
               1.1 => 3,
               true => 4);

    // Multiple identical keys (automated version)
    $x = array(1 => 2,
               3,        // This will be index 2
               2 => 4);  // this index is overwritten
?>

They are indeed overwriting each other. This is most probably a typo.

1.2.12.1. Suggestions

  • Review your code and check that arrays only have keys defined once.
  • Review carefully your code and check indirect values, like constants, static constants.

1.2.12.2. Specs

Short name Arrays/MultipleIdenticalKeys
Rulesets Analyze, CE, CI-checks
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Instant (5 mins)
Precision High
Examples Magento, MediaWiki

1.2.13. Negative Start Index In Array

Negative starting index in arrays changed in PHP 8.0. Until then, they were ignored, and automatic index started always at 0. Since PHP 8.0, the next index is calculated.

The behavior will break code that relies on automatic index in arrays, when a negative index is used for a starter.

<?php

$x = [-5 => 2];
$x[] = 3;

print_r($x);

/*
PHP 7.4 and older
Array
(
    [-5] => 2
    [0] => 3
)
*/

/*
PHP 8.0 and more recent
Array
(
    [-5] => 2
    [-4] => 3
)
*/

?>

See also PHP RFC: Arrays starting with a negative index.

1.2.13.1. Suggestions

  • Explicitely create the index, instead of using the automatic indexing
  • Add an explicit index of 0 in the initial array, to set the automatic process in the right track
  • Avoid using specified index in array, conjointly with automatic indexing.

1.2.13.2. Specs

Short name Arrays/NegativeStart
Rulesets CE, CompatibilityPHP80
Exakt since 2.1.9
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.14. Non-constant Index In Array

Undefined constants revert as strings in Arrays. They are also called barewords.

In $array[index], PHP cannot find index as a constant, but, as a default behavior, turns it into the string index.

This default behavior raise concerns when a corresponding constant is defined, either using define() or the const keyword (outside a class). The definition of the index constant will modify the behavior of the index, as it will now use the constant definition, and not the ‘index’ string.

<?php

// assign 1 to the element index in $array
// index will fallback to string
$array[index] = 1;
//PHP Notice:  Use of undefined constant index - assumed 'index'

echo $array[index];      // display 1 and the above error
echo "$array[index]";    // display 1
echo "$array['index']";  // Syntax error


define('index', 2);

 // now 1 to the element 2 in $array
 $array[index] = 1;

?>

It is recommended to make index a real string (with ‘ or “), or to define the corresponding constant to avoid any future surprise.

Note that PHP 7.2 removes the support for this feature.

See also PHP RFC: Deprecate and Remove Bareword (Unquoted) Strings and Syntax.

1.2.14.1. Suggestions

  • Declare the constant to give it an actual value
  • Turn the constant name into a string

1.2.14.2. Specs

Short name Arrays/NonConstantArray
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Instant (5 mins)
Precision High
Examples Dolibarr, Zencart

1.2.15. No Spread For Hash

The spread operator ... only works on integer-indexed arrays.
<?php

// This is valid, as ``-33`` is cast to integer by PHP automagically
var_dump(...[1,-33 => 2, 3]);

// This is not valid
var_dump(...[1,C => 2, 3]);

?>

See also Variable-length argument lists.

1.2.15.1. Suggestions

  • Add a call to array_values() instead of the hash

1.2.15.2. Specs

Short name Arrays/NoSpreadForHash
Rulesets Analyze
Exakt since 1.9.3
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.16. Null Or Boolean Arrays

Null and booleans are valid PHP array base. Yet, they only produces null values. They also did not emits any warning until PHP 7.4.

This analysis has been upgraded to cover int and float types too.

<?php

// outputs NULL
var_dump(null[0]);

const MY_CONSTANT = true;
// outputs NULL
var_dump(MY_CONSTANT[10]);

?>

See also Null and True.

1.2.16.1. Suggestions

  • Avoid using the array syntax on null and boolean
  • Avoid using null and boolean on constant that are expecting arrays

1.2.16.2. Specs

Short name Arrays/NullBoolean
Rulesets Analyze
Exakt since 1.8.6
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.17. PHP Arrays Index

List of indexes used when manipulating PHP arrays in the code.
<?php

// HTTP_HOST is a PHP array index.
$ip = 'http'.$_SERVER['HTTP_HOST'].'/'.$row['path'];

//'path' is not a PHP index

?>

1.2.17.1. Specs

Short name Arrays/Phparrayindex
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.18. Randomly Sorted Arrays

Those literal arrays are written in several places, but their items are in various orders.

This may reduce the reading and proofing of the arrays, and induce confusion. The random order may also be a residue of development : both arrays started with different values, but they grew overtime to handle the same items. The way they were written lead to the current order.

Unless order is important, it is recommended to always use the same order when defining literal arrays. This makes it easier to match different part of the code by recognizing one of its literal.

<?php

// an array
$set = [1,3,5,9,10];

function foo() {
    // an array, with the same values but different order, in a different context
    $list = [1,3,5,10,9,];
}

// an array, with the same order than the initial one
$inits = [1,3,5,9,10];

?>

1.2.18.1. Suggestions

  • Match the sorting order of the arrays. Choose any of them.
  • Configure a constant and use it as a replacement for those arrays.
  • Leave the arrays intact : the order may be important.
  • For hash arrays, consider turning the array in a class.

1.2.18.2. Specs

Short name Arrays/RandomlySortedLiterals
Rulesets Analyze, Suggestions
Exakt since 0.11.2
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High
Examples Contao, Vanilla

1.2.19. Preprocess Arrays

Using long list of assignations for initializing arrays is significantly slower than the declaring them as an array.
<?php

// Slow way
$a = []; // also with $a = array();
$a[1] = 2;
$a[2] = 3;
$a[3] = 5;
$a[4] = 7;
$a[5] = 11;

// Faster way
$a = [1 => 2,
      2 => 3,
      3 => 5,
      4 => 7,
      5 => 11];

// Even faster way if indexing is implicit
$a = [2, 3, 5, 7, 11];

?>

If the array has to be completed rather than created, it is also faster to use += when there are more than ten elements to add.

<?php

// Slow way
$a = []; // also with $a = array();
$a[1] = 2;
$a[2] = 3;
$a[3] = 5;
// some expressions to get $seven and $eleven
$a[4] = $seven;
$a[5] = $eleven;

// Faster way
$a = [1 => 2,
      2 => 3,
      3 => 5];
// some expressions to get $seven and $eleven
$a += [4 => $seven,
       5 => $eleven];

// Even faster way if indexing is implicit
$a = [2, 3, 5];
// some expressions to get $seven and $eleven
$a += [$seven, $eleven];

?>

1.2.19.1. Suggestions

  • Preprocess the code so PHP doesn’t do it. Keep the detailed version into comments.

1.2.19.2. Specs

Short name Arrays/ShouldPreprocess
Rulesets Suggestions
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.20. Slice Arrays First

Always start by reducing an array before applying some transformation on it. The shorter array will be processed faster.
<?php

// fast version
$a = array_map('foo', array_slice($array, 2, 5));

// slower version
$a = array_slice(array_map('foo', $array), 2, 5);
?>

The gain produced here is greater with longer arrays, or greater reductions. They may also be used in loops. This is a micro-optimisation when used on short arrays.

1.2.20.1. Suggestions

  • Use the array transforming function on the result of the array shortening function.

1.2.20.2. Specs

Short name Arrays/SliceFirst
Rulesets Performances, Suggestions
Exakt since 1.0.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High
Examples WordPress

1.2.21. String Initialization

It used to be possible to initialize a variable with an string, and use it as an array. It is not the case anymore in PHP 7.1.
<?php

// Initialize arrays with array()
$a = array();
$a[3] = 4;

// Don't start with a string
$a = '';
$a[3] = 4;
print $a;

// Don't start with a string
if (is_numeric($a)) {
    $a[] = $a;
}

?>

See also PHP 7.1 no longer converts string to arrays the first time a value is assigned with square bracket notation.

1.2.21.1. Suggestions

  • Always initialize arrays with an empty array(), not a string.

1.2.21.2. Specs

Short name Arrays/StringInitialization
Rulesets CompatibilityPHP71
Exakt since 1.6.5
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.22. Too Many Array Dimensions

When arrays a getting to many nesting.
<?php

$a          = array();   // level 1;
$a[1]       = array();   // level 2
$a[1][2]    = array();   // level 3 : still valid by default
$a[1][2][3] = array();   // level 4

?>

PHP has no limit, and accepts any number of nesting levels. Yet, this is usually very memory hungry.

1.2.22.1. Suggestions

Name Default Type Description
maxDimensions 3 integer Number of valid dimensions in an array.

1.2.22.2. Specs

Short name Arrays/TooManyDimensions
Rulesets Analyze
Exakt since 1.9.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.23. Weird Array Index

Array index that looks weird. Arrays index may be string or integer, but some strings looks weird.

In particular, strings that include terminal white spaces, often leads to missed values.

<?php

$array = ['a ' => 1, 'b' => 2, 'c' => 3];

// Later in the code

//Notice: Undefined index: a in /Users/famille/Desktop/analyzeG3/test.php on line 8
echo $array['a'];

//Notice: Undefined index: b  in /Users/famille/Desktop/analyzeG3/test.php on line 10
// Note that the space is visible, but easy to miss
echo $array['b '];

// all fine here
echo $array['c'];

?>

Although this is rare error, and often easy to spot, it is also very hard to find when it strikes.

1.2.23.1. Suggestions

  • Remove white spaces when using strings as array index.

1.2.23.2. Specs

Short name Arrays/WeirdIndex
Rulesets Semantics
Exakt since 1.9.9
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.24. Handle Arrays With Callback

Use functions like array_map().
<?php

// Handles arrays with callback
$uppercase = array_map('strtoupper', $source);

// Handles arrays with foreach
foreach($source as &$s) {
    $s = uppercase($s);
}

?>

See also array_map.

1.2.24.1. Specs

Short name Arrays/WithCallback
Rulesets CE
Exakt since 1.3.7
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.25. Modify Immutable

A class, marked as immutable, is being modified.

This attribute is supported as a PHPdoc comment, `@immutable, and as a PHP 8.0 attribute.

<?php

/** @Immutable */
#[Immutable]
class x {
    public $x = 1, $y, $z;
}

$x = new X;
// $x->x is modified, while it should not
$x->x = 2 + $x->z;

// $x->z is read only, as expected

?>

See also phpstorm-stubs/meta/attributes/Immutable.php and PhpStorm 2020.3 EAP #4: Custom PHP 8 Attributes.

1.2.25.1. Suggestions

  • Removed the modification
  • Clone the immutable object

1.2.25.2. Specs

Short name Attributes/ModifyImmutable
Rulesets Analyze, Attributes
Exakt since 2.2.0
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision Medium

1.2.26. Abstract Class Usage

List of all abstract classes being used.
<?php

abstract class foo {
    function foobar();
}

class bar extends foo {
    // extended method
    function foobar() {
        // doSomething()
    }

    // extra method
    function barbar() {
        // doSomething()
    }
}
?>

See also Classes abstraction.

1.2.26.1. Specs

Short name Classes/Abstractclass
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.27. Abstract Methods Usage

List of all abstract methods being used.
<?php

// abstract class
abstract class foo {
    // abstract method
    function foobar();
}

class bar extends foo {
    // extended abstract method
    function foobar() {
        // doSomething()
    }

    // extra method
    function barbar() {
        // doSomething()
    }
}
?>

See also Classes abstraction.

1.2.27.1. Specs

Short name Classes/Abstractmethods
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.28. Abstract Or Implements

A class must implements all abstract methods of it parent, or be abstract too.

While PHP lints this code, it won’t execute it and stop with a Fatal Error : Class BA contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (A\:\:aFoo).

<?php

abstract class Foo {
    abstract function FooBar();
}

// This is in another file : php -l would detect it right away

class FooFoo extends Foo {
    // The method is not defined.
    // The class must be abstract, just like Foo
}

?>

See also Class Abstraction.

1.2.28.1. Suggestions

  • Implements all the abstract methods of the class
  • Make the class abstract

1.2.28.2. Specs

Short name Classes/AbstractOrImplements
Rulesets Analyze, LintButWontExec
Exakt since 1.3.3
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High
Examples Zurmo

1.2.29. Abstract Static Methods

Methods cannot be both abstract and static. Static methods belong to a class, and will not be overridden by the child class. For normal methods, PHP will start at the object level, then go up the hierarchy to find the method. With static, it is necessary to mention the name, or use Late Static Binding, with self or static. Hence, it is useless to have an abstract static method : it should be a static method.

A child class is able to declare a method with the same name than a static method in the parent, but those two methods will stay independent.

This is not the case anymore in PHP 7.0+.

<?php

abstract class foo {
    // This is not possible
    static abstract function bar() ;
}

?>

See also Why does PHP 5.2+ disallow abstract `static class methods? <https://stackoverflow.com/questions/999066/why-does-php-5-2-disallow-abstract-static-class-methods>`_.

1.2.29.1. Suggestions

  • Remove abstract keyword from the method
  • Remove static keyword from the method
  • Remove the method

1.2.29.2. Specs

Short name Classes/AbstractStatic
Rulesets Analyze
Exakt since 0.8.4
Php Version 7.0-
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.30. Accessing Private

List of calls to private properties/methods that will compile but yield some fatal error upon execution.
<?php

class a {
    private $a;
}

class b extends a {
    function c() {
        $this->a;
    }
}

?>

1.2.30.1. Specs

Short name Classes/AccessPrivate
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High

1.2.31. Access Protected Structures

It is not allowed to access protected properties or methods from outside the class or its relatives.
<?php

class foo {
    protected $bar = 1;
}

$foo = new Foo();
$foo->bar = 2;

?>

See also Visibility and Understanding The Concept Of Visibility In Object Oriented PHP.

1.2.31.1. Suggestions

  • Change ‘protected’ to ‘public’ to relax the constraint
  • Add a getter method to reach the target value
  • Remove the access to the protected value and find it another way

1.2.31.2. Specs

Short name Classes/AccessProtected
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High

1.2.32. Ambiguous Static

Methods or properties with the same name, are defined static in one class, and not static in another. This is error prone, as it requires a good knowledge of the code to make it static or not.

Try to keep the methods simple and unique. Consider renaming the methods and properties to distinguish them easily. A method and a static method have probably different responsibilities.

<?php

class a {
    function mixedStaticMethod() {}
}

class b {
    static function mixedStaticMethod() {}
}

/... a lot more code later .../

$c->mixedStaticMethod();
// or
$c::mixedStaticMethod();

?>

1.2.32.1. Specs

Short name Classes/AmbiguousStatic
Rulesets Analyze
Exakt since 1.0.3
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.33. Ambiguous Visibilities

The properties have the same name, but have different visibilities, across different classes.

While it is legit to have a property with the same name in different classes, it may easily lead to confusion. As soon as the context is need to understand if the property is accessible or not, the readability suffers.

It is recommended to handle the same properties in the same way across classes, even when the classes are not related.

<?php

class person {
    public $name;
    private $address;
}

class gangster {
    private $name;
    public $nickname;
    private $address;
}

$someone = Human::load(123);
echo 'Hello, '.$someone->name;

?>

1.2.33.1. Suggestions

  • Sync visibilities for both properties, in the different classes
  • Use different names for properties with different usages

1.2.33.2. Specs

Short name Classes/AmbiguousVisibilities
Rulesets Analyze
Exakt since 1.3.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High
Examples Typo3

1.2.34. Anonymous Classes

Anonymous classes.
<?php

// Anonymous class, available since PHP 7.0
$object = new class { function __construct() { echo __METHOD__; } };

?>

1.2.34.1. Specs

Short name Classes/Anonymous
Rulesets CE, CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56
Exakt since 0.8.4
Php Version 7.0+
Severity Major
Time To Fix Slow (1 hour)
Precision High

1.2.35. Avoid Optional Properties

Avoid optional properties, to prevent littering the code with existence checks.

When a property has to be checked once for existence, it is safer to check it each time. This leads to a decrease in readability and a lot of checks added to the code.

Either make sure the property is set with an actual object rather than with null, or use a null object. A null object offers the same interface than the expected object, but does nothing. It allows calling its methods, without running into a Fatal error, nor testing it.

<?php

// Example is courtesy 'The Coding Machine' : it has been adapted from its original form. See link below.

class MyMailer {
    private $logger;

    public function __construct(LoggerInterface $logger = null) {
        $this->logger = $logger;
    }

    private function sendMail(Mail $mail) {
        // Since $this->logger may be null, it must be tested anytime it is used.
        if ($this->logger) {
            $this->logger->info('Mail successfully sent.');
        }
    }
}

?>

See also Avoid optional services as much as possible, The Null Object Pattern – Polymorphism in Domain Models, and Practical PHP Refactoring: Introduce Null Object.

1.2.35.1. Suggestions

  • Use a null object to fill any missing value
  • Make sure the property is set at constructor time

1.2.35.2. Specs

Short name Classes/AvoidOptionalProperties
Rulesets Analyze
Exakt since 0.12.0
Php Version All
Severity Major
Time To Fix Slow (1 hour)
Precision High
Examples ChurchCRM, Dolibarr

1.2.36. Avoid option arrays in constructors

Avoid option arrays in constructors. Use one parameter per injected element.
<?php

class Foo {
    // Distinct arguments, all typehinted if possible
    function __constructor(A $a, B $b, C $c, D $d) {
        $this->a = $a;
        $this->b = $b;
        $this->c = $c;
        $this->d = $d;
    }
}

class Bar {
    // One argument, spread over several properties
    function __constructor(array $options) {
        $this->a = $options['a'];
        $this->b = $options['b'];
        $this->c = $options['c'];
        $this->d = $options['d'];
    }
}

?>

See also Avoid option arrays in constructors and PHP RFC: Named Arguments (Type-safe and documented options).

1.2.36.1. Suggestions

  • Spread the options in the argument list, one argument each
  • Use a configuration class, that hold all the elements with clear names, instead of an array
  • Use named parameters to pass and document the arguments

1.2.36.2. Specs

Short name Classes/AvoidOptionArrays
Rulesets Analyze, ClassReview
Exakt since 1.7.9
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision Medium

1.2.37. Custom Class Usage

List of usage of custom classes throughout the code.
Name Default Type Description
forbiddenClasses   ini_hash List of classes to be avoided

1.2.37.1. Specs

Short name Classes/AvoidUsing
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Slow (1 hour)
Precision High

1.2.38. Cancel Common Method

A parent method’s is too little used in children.

The parent class has a method, which is customised in children classes, though most of the time, those are empty : hence, cancelled.

<?php

class x {
    abstract function foo();
    abstract function bar();
}

class y1 extends x {
    function foo() { doSomething(); }
    function bar() { doSomething(); };
}

class y2 extends x {
    // foo is cancelled : it must be written, but has no use.
    function foo() {  }
    function bar() { doSomething(); };
}

?>

A threshold of cancelThreshold % of the children methods have to be cancelled to report the parent class. By default, it is 75 (or 3 out of 4).

1.2.38.1. Suggestions

  • Drop the common method, and the cancelled methods in the children
  • Fill the children’s methods with actual code
Name Default Type Description
cancelThreshold 75 integer Minimal number of cancelled methods to suggest the cancellation of the parent.

1.2.38.2. Specs

Short name Classes/CancelCommonMethod
Rulesets ClassReview, Suggestions
Exakt since 2.1.8
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.39. Can’t Extend Final

It is not possible to extend final classes.

Since PHP fails with a fatal error, this means that the extending class is probably not used in the rest of the code. Check for dead code.

<?php
    // File Foo
    final class foo {
        public final function bar() {
            // doSomething
        }
    }
?>

In a separate file :

<?php
    // File Bar
    class bar extends foo {

    }
?>

See also Final Keyword.

1.2.39.1. Suggestions

  • Remove the final keyword
  • Remove the extending class

1.2.39.2. Specs

Short name Classes/CantExtendFinal
Rulesets Analyze, Dead code
Exakt since 0.8.4
Php Version All
Severity Critical
Time To Fix Instant (5 mins)
Precision Medium

1.2.40. Cant Inherit Abstract Method

Inheriting abstract methods was made available in PHP 7.2. In previous versions, it emitted a fatal error.
<?php

abstract class A           { abstract function bar(stdClass $x);  }
abstract class B extends A { abstract function bar($x): stdClass; }

//   Fatal error: Can't inherit abstract function A::bar()
?>

See also PHP RFC: Allow abstract function override.

1.2.40.1. Suggestions

  • Avoid inheriting abstract methods for compatibility beyond 7.2 (and older)

1.2.40.2. Specs

Short name Classes/CantInheritAbstractMethod
Rulesets CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56, CompatibilityPHP70, CompatibilityPHP71
Exakt since 0.11.8
Php Version 7.2+
Severity Critical
Time To Fix Quick (30 mins)
Precision High

1.2.41. Cant Instantiate Class

When constructor is not public, it is not possible to instantiate such a class. Either this is a conception choice, or there are factories to handle that. Either way, it is not possible to call new on such class.

PHP reports an error similar to this one : ‘Call to private Y::__construct() from invalid context’.

<?php

//This is the way to go
$x = X::factory();

//This is not possible
$x = new X();

class X {
    //This is also the case with proctected __construct
    private function __construct() {}

    static public function factory() {
        return new X();
    }
}

?>

See also In a PHP5 class, when does a private constructor get called?, Named Constructors in PHP and PHP Constructor Best Practices And The Prototype Pattern.

1.2.41.1. Specs

Short name Classes/CantInstantiateClass
Rulesets Analyze
Exakt since 1.2.8
Php Version All
Severity Critical
Time To Fix Quick (30 mins)
Precision High
Examples WordPress

1.2.42. Check On __Call Usage

When using the magic methods __call() and __staticcall(), make sure the method exists before calling it.

If the method doesn’t exists, then the same method will be called again, leading to the same failure. Finally, it will crash PHP.

<?php

class safeCall {
    function __class($name, $args) {
        // unsafe call, no checks
        if (method_exists($this, $name)) {
            $this->$name(...$args);
        }
    }
}

class unsafeCall {
    function __class($name, $args) {
        // unsafe call, no checks
        $this->$name(...$args);
    }
}

?>

See also Method overloading and ``Magical PHP: __call <https://www.garfieldtech.com/index.php/blog/magical-php-call>`_.

1.2.42.1. Suggestions

  • Add a call to method_exists() before using any method name
  • Relay the call to another object that doesn’t handle __call() or __callStatic()

1.2.42.2. Specs

Short name Classes/CheckOnCallUsage
Rulesets Analyze, CE, CI-checks
Exakt since 1.7.2
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.43. Child Class Removes Typehint

PHP 7.2 introduced the ability to remove a typehint when overloading a method. This is not valid code for older versions.
<?php

class foo {
    function foobar(foo $a) {}
}

class bar extends foo {
    function foobar($a) {}
}

?>

1.2.43.1. Specs

Short name Classes/ChildRemoveTypehint
Rulesets CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56, CompatibilityPHP70, CompatibilityPHP71, Typechecks
Exakt since 0.12.4
Php Version 7.2+
Severity Major
Time To Fix Quick (30 mins)
Precision High

1.2.44. Class, Interface Or Trait With Identical Names

The following names are used at the same time for classes, interfaces or traits. For example,
<?php
    class a     { /* some definitions */ }
    interface a { /* some definitions */ }
    trait a     { /* some definitions */ }
?>

Even if they are in different namespaces, identical names makes classes easy to confuse. This is often solved by using alias at import time : this leads to more confusion, as a class suddenly changes its name.

Internally, PHP use the same list for all classes, interfaces and traits. As such, it is not allowed to have both a trait and a class with the same name.

In PHP 4, and PHP 5 before namespaces, it was not possible to have classes with the same name. They were simply included after a check.

1.2.44.1. Suggestions

  • Use distinct names for every class, trait and interface.
  • Keep eponymous classes, traits and interfaces in distinct files, for definition but also for usage. When this happens, rename one of them.

1.2.44.2. Specs

Short name Classes/CitSameName
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High
Examples shopware, NextCloud

1.2.45. Usage Of class_alias()

class_alias creates dynamically an alias for classes.
<?php

class foo { }

class_alias('foo', 'bar');

$a = new foo;
$b = new bar;

// the objects are the same
var_dump($a == $b, $a === $b);
var_dump($a instanceof $b);

// the classes are the same
var_dump($a instanceof foo);
var_dump($a instanceof bar);

var_dump($b instanceof foo);
var_dump($b instanceof bar);

?>

See also class_alias.

1.2.45.1. Specs

Short name Classes/ClassAliasUsage
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.46. Classes Names

List of all classes, as defined in the application.
<?php

// foo is in the list
class foo {}

// Anonymous classes are not in the list
$o = class { function foo(){} }

?>

1.2.46.1. Specs

Short name Classes/Classnames
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.47. Class Usage

List of classes being used.
<?php

// Class may be used in a use expression
use MyClass as MyAliasedClass;

// class may be aliased with class_alias
class_alias('MyOtherAliasedClass', 'MyClass');

// Class may be instanciated
$o = new MyClass();

// Class may be used with instanceof
var_dump($o instanceof \MyClass);

// Class may be used in static calls
MyClass::aConstant;
echo MyClass::$aProperty;
echo MyClass::aMethod( $o );

// Class may be extended
class MyOtherClass {

}

class MyClass extends MyOtherClass {
    const aConstant = 1;

    public static $aProperty = 2;

    // also used as a typehint
    public static function aMethod(MyClass $object) {
        return __METHOD__;
    }
}

?>

1.2.47.1. Specs

Short name Classes/ClassUsage
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.48. Clone With Non-Object

The clone keyword must be used on variables, properties or results from a function or method call.

clone cannot be used with constants or literals.

<?php

class x { }
$x = new x();

// Valid clone
$y = clone $x;

// Invalid clone
$y = clone x;

?>

Cloning a non-object lint but won’t execute.

See also Object cloning.

1.2.48.1. Suggestions

  • Only clone containers (like variables, properties…)
  • Add typehint to injected properties, so they are checked as objects.

1.2.48.2. Specs

Short name Classes/CloneWithNonObject
Rulesets Analyze, LintButWontExec
Exakt since 1.7.0
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.49. Clone Usage

List of all clone situations.
<?php
    $dateTime = new DateTime();
    echo (clone $dateTime)->format('Y');
?>

See also Object cloning.

1.2.49.1. Specs

Short name Classes/CloningUsage
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.50. Constant Class

A class or an interface only made up of constants. Constants usually have to be used in conjunction of some behavior (methods, class…) and never alone.
<?php

class ConstantClass {
    const KBIT = 1000;
    const MBIT = self::KBIT * 1000;
    const GBIT = self::MBIT * 1000;
    const PBIT = self::GBIT * 1000;
}

?>

As such, they should be PHP constants (build with define or const), or included in a class with other methods and properties.

See also PHP Classes containing only constants.

1.2.50.1. Suggestions

  • Make the class an interface
  • Make the class an abstract class, to avoid its instantiation

1.2.50.2. Specs

Short name Classes/ConstantClass
Rulesets CE, ClassReview
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.51. Constant Definition

List of class constants being defined.
<?php

// traditional way of making constants
define('aConstant', 1);

// modern way of making constants
const anotherConstant = 2;

class foo {
    // Not a constant, a class constant.
    const aClassConstant = 3;
}

?>

See also PHP Constants.

1.2.51.1. Specs

Short name Classes/ConstantDefinition
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.52. Constant Used Below

Mark class constants that are used in children classes.
<?php

class foo {
    // This constant is used in children
    protected PROTECTEDPROPERTY = 1;

    // This constant is not used in children
    protected LOCALPROTECTEDPROPERTY = 1;

    private function foobar() {
        // PROTECTEDPROPERTY is used here, but defined in parent
        echo self::LOCALPROTECTEDPROPERTY;
    }
}

class foofoo extends foo {
    private function bar() {
        // protectedProperty is used here, but defined in parent
        print self::PROTECTEDPROPERTY;
    }
}

?>

This analysis marks constants at their definition, not the current class, nor the (grand-)`parent <https://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php>`_.

1.2.52.1. Specs

Short name Classes/ConstantUsedBelow
Rulesets none
Exakt since 0.12.10
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.53. Constructors

Mark methods as constructors.
<?php

class x {
    // Normal constructor
    function __construct() {}
}

class y {
    // Old style constructor, obsolete since PHP 7.1
    function y() {}
}

class z {
    // Normal constructor
    function __construct() {}

    // Old style constructor, but with lower priority
    function z() {}
}

?>

See also Constructors and Destructors.

1.2.53.1. Specs

Short name Classes/Constructor
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.54. Const Visibility Usage

Visibility for class constant controls the accessibility to class constant.

A public constant may be used anywhere in the code; a protected constant usage is restricted to the class and its relatives; a private constant is restricted to itself.

This feature was introduced in PHP 7.1. It is recommended to use explicit visibility, and, whenever possible, make the visibility private.

<?php

class x {
    public const a = 1;
    protected const b = 2;
    private const c = 3;
    const d = 4;
}

interface i {
    public const a = 1;
      const d = 4;
}

?>

See also Class Constants and PHP RFC: Support Class Constant Visibility.

1.2.54.1. Suggestions

  • Add constant visibility, at least ‘public’.

1.2.54.2. Specs

Short name Classes/ConstVisibilityUsage
Rulesets CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56, CompatibilityPHP70
Exakt since 1.3.0
Php Version 7.1+
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.55. Could Be Abstract Class

An abstract class is never instantiated, and has children class that are. As such, a ‘parent’ class that is never instantiated by itself, but has its own children instantiated could be marked as abstract.

That will prevent new code to try to instantiate it.

<?php

// Example code would actually be split over multiple files.


// That class could be abstract
class motherClass {}

// Those classes shouldn't be abstract
class firstChildren extends motherClass {}
class secondChildren extends motherClass {}
class thirdChildren extends motherClass {}

new firstChildren();
new secondChildren();
new thirdChildren();

//Not a single : new motherClass()

?>

See also Class Abstraction Abstract classes and methods.

1.2.55.1. Suggestions

  • Make this class an abstract class

1.2.55.2. Specs

Short name Classes/CouldBeAbstractClass
Rulesets Analyze, ClassReview
Exakt since 1.3.9
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High
Examples Edusoho, shopware

1.2.56. Could Be Class Constant

When a property is defined and read, but never modified, it may be a constant.
<?php

class foo {
    // $this->bar is never modified.
    private $bar = 1;

    // $this->foofoo is modified, at least once
    private $foofoo = 2;

    function method($a) {
        $this->foofoo = $this->bar + $a + $this->foofoo;

        return $this->foofoo;
    }

}

?>

Starting with PHP 5.6, even array() may be defined as constants.

1.2.56.1. Specs

Short name Classes/CouldBeClassConstant
Rulesets ClassReview
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.57. Class Could Be Final

Any class that has no extension should be final by default.

As stated by Matthias Noback : If a class is not marked final, it has at least one subclass.

Prevent your classes from being subclassed by making them final. Sometimes, classes are not meant or thought to be derivable.

<?php

class x {}            // This class is extended
class y extends x {}  // This class is extended
class z extends y {}  // This class is not extended

final class z2 extends y {}  // This class is not extended

?>

See also Negative architecture, and assumptions about code.

1.2.57.1. Suggestions

  • Make the class final
  • Extends the class

1.2.57.2. Specs

Short name Classes/CouldBeFinal
Rulesets Analyze, ClassReview
Exakt since 1.4.3
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.58. Could Be Parent Method

A method is defined in several children, but not in a the parent class. It may be worth checking if this method doesn’t belong the parent class, as an abstraction.
<?php

// The parent class
class x { }

// The children class
class y1 extends x {
    // foo is common to y1 and y2, so it shall be also a method in x
    function foo() {}
    // fooY1 is specific to y1
    function fooY1() {}
}

class y2 extends x {
    function foo() {}
    // fooY2 is specific to y1
    function fooY2() {}
}

?>

Only the name of the method is used is for gathering purposes. If the code has grown organically, the signature (default values, typehint, argument names) may have followed different path, and will require a refactorisation.

1.2.58.1. Suggestions

  • Create an abstract method in the parent
  • Create an concrete method in the parent, and move default behavior there by removing it in children classes
Name Default Type Description
minChildren 4 integer Minimal number of children using this method.

1.2.58.2. Specs

Short name Classes/CouldBeParentMethod
Rulesets ClassReview
Exakt since 2.1.7
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.59. Property Could Be Private Property

The following properties are never used outside their class of definition Given the analyzed code, they could be set as private.
<?php

class foo {
    public $couldBePrivate = 1;
    public $cantdBePrivate = 1;

    function bar() {
        // couldBePrivate is used internally.
        $this->couldBePrivate = 3;
    }
}

class foo2 extends foo {
    function bar2() {
        // cantdBePrivate is used in a child class.
        $this->cantdBePrivate = 3;
    }
}

//$couldBePrivate is not used outside
$foo = new foo();

//$cantdBePrivate is used outside the class
$foo->cantdBePrivate = 2;

?>

Note that dynamic properties (such as $x->$y) are not taken into account.

1.2.59.1. Suggestions

  • Remove the unused property
  • Use the private property
  • Change the visibility to allow access the property from other part of the code

1.2.59.2. Specs

Short name Classes/CouldBePrivate
Rulesets ClassReview
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.60. Could Be Private Class Constant

Class constant may use private visibility.

Since PHP 7.1, constants may also have a public/protected/private visibility. This restrict their usage to anywhere, class and children or class.

As a general rule, it is recommended to make constant private by default, and to relax this restriction as needed. PHP makes them public by default.

<?php

class foo {
    // pre-7.1 style
    const PRE_71_CONSTANT = 1;

    // post-7.1 style
    private const PRIVATE_CONSTANT = 2;
    public const PUBLIC_CONSTANT = 3;

    function bar() {
        // PRIVATE CONSTANT may only be used in its class
        echo self::PRIVATE_CONSTANT;
    }
}

// Other constants may be used anywhere
function x($a = foo::PUBLIC_CONSTANT) {
    echo $a.' '.foo:PRE_71_CONSTANT;
}

?>

Constant shall stay public when the code has to be compatible with PHP 7.0 and older.

They also have to be public in the case of component : some of those constants have to be used by external actors, in order to configure the component.

See also Class Constants.

1.2.60.1. Specs

Short name Classes/CouldBePrivateConstante
Rulesets ClassReview
Exakt since 0.12.10
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High
Examples Phinx

1.2.61. Method Could Be Private Method

The following methods are never used outside their class of definition. Given the analyzed code, they could be set as private.
<?php

class foo {
    public function couldBePrivate() {}
    public function cantdBePrivate() {}

    function bar() {
        // couldBePrivate is used internally.
        $this->couldBePrivate();
    }
}

class foo2 extends foo {
    function bar2() {
        // cantdBePrivate is used in a child class.
        $this->cantdBePrivate();
    }
}

//couldBePrivate() is not used outside
$foo = new foo();

//cantdBePrivate is used outside the class
$foo->cantdBePrivate();

?>

Note that dynamic properties (such as $x->$y) are not taken into account.

1.2.61.1. Specs

Short name Classes/CouldBePrivateMethod
Rulesets ClassReview
Exakt since 0.12.11
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.62. Could Be Protected Class Constant

Class constant may use ‘protected’ visibility.

Since PHP 7.1, constants may also have a public/protected/private visibility. This restrict their usage to anywhere, class and children or class.

As a general rule, it is recommended to make constant ‘private’ by default, and to relax this restriction as needed. PHP makes them public by default.

<?php

class foo {
    // pre-7.1 style
    const PRE_71_CONSTANT = 1;

    // post-7.1 style
    protected const PROTECTED_CONSTANT = 2;
    public const PUBLIC_CONSTANT = 3;
}

class foo2 extends foo {
    function bar() {
        // PROTECTED_CONSTANT may only be used in its class or its children
        echo self::PROTECTED_CONSTANT;
    }
}

class foo3 extends foo {
    function bar() {
        // PROTECTED_CONSTANT may only be used in its class or any of its children
        echo self::PROTECTED_CONSTANT;
    }
}

// Other constants may be used anywhere
function x($a = foo::PUBLIC_CONSTANT) {
    echo $a.' '.foo:PRE_71_CONSTANT;
}

?>

1.2.62.1. Specs

Short name Classes/CouldBeProtectedConstant
Rulesets ClassReview
Exakt since 0.12.11
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.63. Could Be Protected Method

Those methods are declared public, but are never used publicly. They may be made protected.
<?php

class foo {
    // Public, and used publicly
    public publicMethod() {}

    // Public, but never used outside the class or its children
    public protectedMethod() {}

    private function bar() {
        $this->protectedMethod();
    }
}

$foo = new Foo();
$foo->publicMethod();

?>

These properties may even be made private.

1.2.63.1. Specs

Short name Classes/CouldBeProtectedMethod
Rulesets ClassReview
Exakt since 0.12.11
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.64. Could Be Protected Property

Those properties are declared public, but are never used publicly. They may be made protected.
<?php

class foo {
    // Public, and used publicly
    public $publicProperty;
    // Public, but never used outside the class or its children
    public $protectedProperty;

    function bar() {
        $this->protectedProperty = 1;
    }
}

$foo = new Foo();
$foo->publicProperty = 3;

?>

This property may even be made private.

1.2.64.1. Specs

Short name Classes/CouldBeProtectedProperty
Rulesets ClassReview
Exakt since 0.9.7
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.65. Method Could Be Static

A method that doesn’t make any usage of $this could be turned into a static method.

While static methods are usually harder to handle, recognizing the static status is a first step before turning the method into a standalone function.

<?php

class foo {
    static $property = 1;

    // legit static method
    static function staticMethod() {
        return self::$property;
    }

    // This is not using $this, and could be static
    function nonStaticMethod() {
        return self::$property;
    }

    // This is not using $this nor self, could be a standalone function
    function nonStaticMethod() {
        return self::$property;
    }
}

?>

1.2.65.1. Suggestions

  • Make the method static
  • Make the method a standalone function
  • Make use of $this in the method : may be it was forgotten.

1.2.65.2. Specs

Short name Classes/CouldBeStatic
Rulesets Analyze, ClassReview
Exakt since 1.5.7
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High
Examples FuelCMS, ExpressionEngine

1.2.66. Could Be Stringable

Stringable is an interface that mark classes as string-castable. It is introduced in PHP 8.0.

Classes that defined a __toString() magic method may be turned into a string when the typehint, argument, return or property, requires it. This is not the case when strict_types is activated. Yet, until PHP 8.0, there was nothing to identify a class as such.

<?php

// This class may implement Stringable
class x {
    function __tostring() {
        return 'asd';
    }
}

echo (new x);

?>

See also PHP RFC: Add Stringable interface.

1.2.66.1. Suggestions

1.2.66.2. Specs

Short name Classes/CouldBeStringable
Rulesets Analyze, LintButWontExec
Exakt since 2.1.9
Php Version 8.0+
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.67. Cyclic References

Avoid cyclic references.

Cyclic references happen when an object points to another object, which reciprocate. This is particularly possible with classes, when the child class has to keep a reference to the parent class.

<?php

class a {
    private $p = null;

    function foo() {
        $this->p = new b();
        // the current class is stored in the child class
        $this->p->m($this);
    }
}

class b {
    private $pb = null;

    function n($a) {
        // the current class keeps a link to its parent
        $this->pb = $a;
    }
}
?>

Cyclic references, or circular references, are memory intensive : only the garbage collector can understand when they may be flushed from memory, which is a costly operation. On the other hand, in an acyclic reference code, the reference counter will know immediately know that an object is free or not.

See also About circular references in PHP and A Journey to find a memory leak.

1.2.67.1. Suggestions

  • Use a different object when calling the child objects.
  • Refactor your code to avoid the cyclic reference.

1.2.67.2. Specs

Short name Classes/CyclicReferences
Rulesets Analyze, ClassReview
Exakt since 2.1.3
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.68. Defined Class Constants

Connect class constants with their definition when it can find it. This includes class constants, one level of parent (extended) or interfaces (implemented).
<?php

class X {
    const Y = 2;

    function foo() {
        // This is defined on the line above
        echo self::Y;

        // This is not defined in the current code
        echo X::X;
    }
}

?>

1.2.68.1. Specs

Short name Classes/DefinedConstants
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.69. Defined Parent MP

Check static calls with ‘parent’.
<?php

class foo {
    protected function parentDefined() {}
    protected function unusedParentMethod() {}

    // visibility is checked too
    protected function unusuableParentMethod() {}
}

class bar extends foo {

    private function someMethod() {
        // reported
        parent::parentDefined();

        // not reported, as method is unreachable in parent
        parent::unusuableParentMethod();

        // not reported, as method is undefined in parent
        parent::parentUndefined();

    }

    protected function parentDefined2() {}
}

?>

1.2.69.1. Specs

Short name Classes/DefinedParentMP
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.70. Defined Properties

List of properties that are explicitly defined in the class, its parents or traits.
<?php

class foo {
    // property definition
    private bar = 2;
}

?>

See also Properties.

1.2.70.1. Specs

Short name Classes/DefinedProperty
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.71. Defined static:: Or self::

List of all defined static and self properties and methods.
<?php

class x {
    static public function definedStatic() {}
    private definedStatic = 1;

    public function method() {
        self::definedStatic();
        self::undefinedStatic();

        static::definedStatic;
        static::undefinedStatic;
    }
}

?>

1.2.71.1. Specs

Short name Classes/DefinedStaticMP
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.72. Law of Demeter

The law of Demeter specifies a number of constraints to apply to methodcalls from within an method, so as to keep dependencies to a minimum.
<?php

class x {
    function foo($arg) {
        $this->foo();    // calling oneself is OK
        $this->x->bar(); // calling one's property is OK
        $arg->bar2();    // calling arg's methods is OK

        $local = new y();
        $z = $y->bar3();      // calling a local variable is OK

        $z->bar4();      // calling a method on a previous result is wrong
    }
}

?>

See also Do your objects talk to strangers? and Law of Demeter.

1.2.72.1. Suggestions

1.2.72.2. Specs

Short name Classes/DemeterLaw
Rulesets none
Exakt since 1.6.7
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.73. Dependant Abstract Classes

Abstract classes should be autonomous. It is recommended to avoid depending on methods, constant or properties that should be made available in inheriting classes, without explicitly abstracting them.

The following abstract classes make usage of constant, methods and properties, static or not, that are not defined in the class. This means the inheriting classes must provide those constants, methods and properties, but there is no way to enforce this.

This may also lead to dead code : when the abstract class is removed, the host class have unused properties and methods.

<?php

// autonomous abstract class : all it needs is within the class
abstract class c {
    private $p = 0;

    function foo() {
        return ++$this->p;
    }
}

// dependant abstract class : the inheriting classes needs to provide some properties or methods
abstract class c2 {
    function foo() {
        // $p must be provided by the extending class
        return ++$this->p;
    }
}

class c3 extends c2 {
    private $p = 0;
}
?>

See also Dependant Trait.

1.2.73.1. Suggestions

  • Make the class only use its own resources
  • Split the class in autonomous classes
  • Add local property definitions to make the class independent

1.2.73.2. Specs

Short name Classes/DependantAbstractClass
Rulesets Analyze, ClassReview
Exakt since 1.8.6
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.74. Different Argument Counts

Two methods with the same name shall have the same number of compulsory argument. PHP accepts different number of arguments between two methods, if the extra arguments have default values. Basically, they shall be called interchangeably with the same number of arguments.

The number of compulsory arguments is often mistaken for the same number of arguments. When this is the case, it leads to confusion between the two signatures. It will also create more difficulties when refactoring the signature.

While this code is legit, it is recommended to check if the two signatures could be synchronized, and reduce future surprises.

<?php

class x {
    function foo($a ) {}
}

class y extends x {
    // This method is compatible with the above, its signature is different
    function foo($a, $b = 1) {}
}

?>

1.2.74.1. Suggestions

  • Extract the extra arguments into other methods
  • Remove the extra arguments
  • Add the extra arguments to all the signatures

1.2.74.2. Specs

Short name Classes/DifferentArgumentCounts
Rulesets Analyze, ClassReview
Exakt since 2.1.6
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.75. No Direct Call To Magic Method

PHP features magic methods, which are methods related to operators.

Magic methods, such as __get(), related to =, or __clone(), related to clone, are supposed to be used in an object environment, and not with direct call.

It is recommended to use the magic method with its intended usage, and not to call it directly. For example, typecast to string instead of calling the __toString() method.

<?php
// Write
  print $x->a;
// instead of
  print $x->__get('a');

class Foo {
    private $b = secret;

    public function __toString() {
        return strtoupper($this->b);
    }
}

$bar = new Foo();
echo (string) $bar;

?>

Accessing those methods in a static way is also discouraged.

See also Magic Methods and Magical PHP: `__call <https://www.garfieldtech.com/blog/magical-php-call>`_.

1.2.75.1. Specs

Short name Classes/DirectCallToMagicMethod
Rulesets Analyze, CE, CI-checks
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High

1.2.76. Disconnected Classes

One class is extending the other, but they do not use any features from one another. Basically, those two classes are using extends, but they are completely independent and may be separated.

When using the ‘extends’ keyword, the newly created classes are now acting together and making one. This should be visible in calls from one class to the other, or simply by property usage : they can’t live without each other.

On the other hand, two completely independent classes that are merged, although they should be kept separated.

<?php

class A {
    private $pa = 1;

    function fooA() {
        $this->pa = 2;
    }
}

// class B and Class A are totally independent
class B extends A {
    private $pb = 1;

    function fooB() {
        $this->pb = 2;
    }
}


// class C makes use of class A : it is dependent on the parent class
class C extends A {
    private $pc = 1;

    function fooB() {
        $this->pc = 2 + $this->fooA();
    }
}
?>

1.2.76.1. Suggestions

  • Remove the extension
  • Make actual usage of the classes, at least from one of them

1.2.76.2. Specs

Short name Classes/DisconnectedClasses
Rulesets ClassReview
Exakt since 1.8.9
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High
Examples WordPress

1.2.77. Don’t Send $this In Constructor

Don’t use $this as an argument while in the __construct(). Until the constructor is finished, the object is not finished, and may be in an unstable state. Providing it to another code may lead to error.

This is true when the receiving structure puts the incoming object immediately to work, and don’t store it for later use.

<?php

// $this is only provided when Foo is constructed
class Foo {
    private $bar = null;
    private $data = array();

    static public function build($data) {
        $foo = new Foo($data);
        // Can't build in one call. Must make it separate.
        $foo->finalize();
    }

    private function __construct($data) {
        // $this is provided too early
        $this->data = $data;
    }

    function finalize() {
        $this->bar = new Bar($this);
    }
}

// $this is provided too early, leading to error in Bar
class Foo2 extends Foo {
    private $bar = null;
    private $data = array();

    function __construct($data) {
        // $this is provided too early
        $this->bar = new Bar($this);
        $this->data = $data;
    }
}

class Bar {
    function __construct(Foo $foo) {
        // the cache is now initialized with a wrong
        $this->cache = $foo->getIt();
    }
}

?>

See also Don’t pass this out of a constructor.

1.2.77.1. Suggestions

  • Finish the constructor first, then call an external object.
  • Sending $this should be made accessible in a separate method, so external objects may call it.
  • Sending the current may be the responsibility of the method creating the object.

1.2.77.2. Specs

Short name Classes/DontSendThisInConstructor
Rulesets Analyze
Exakt since 1.0.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High
Examples Woocommerce, Contao

1.2.78. Don’t Unset Properties

Avoid unsetting properties. They would go undefined, and raise more warnings.

When getting rid of a property, assign it to null. This keeps the property in the object, yet allows existence check without errors.

<?php

class Foo {
    public $a = 1;
}

$a = new Foo();

var_dump((array) $a) ;
// la propriété est reportée, et null
// ['a' => null]

unset($a->a);

var_dump((array) $a) ;
//Empty []

// Check if a property exists
var_dump($a->b === null);

// Same result as above, but with a warning
var_dump($a->c === null);

?>

This analysis works on properties and static properties. It also reports magic properties being unset.

Thanks for Benoit Burnichon for the original idea.

1.2.78.1. Suggestions

  • Never unset properties : set it to null or its default value instead
  • Make the property an array, and set/unset its index

1.2.78.2. Specs

Short name Classes/DontUnsetProperties
Rulesets Analyze, CE, CI-checks, Top10, php-cs-fixable
Exakt since 1.2.3
Php Version All
Severity Major
Time To Fix Slow (1 hour)
Precision High
Examples Vanilla, Typo3

1.2.79. Dynamic Classes

Dynamic calls of classes.
<?php

class x {
    static function staticMethod() {}
}

$class = 'x';
$class::staticMethod();

?>

1.2.79.1. Specs

Short name Classes/DynamicClass
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.80. Dynamic Class Constant

Dynamic calls to class constants.

Constant may be dynamically called with the constant() function.

<?php
    // Dynamic access to 'E_ALL'
    echo constant('E_ALL');

    interface i {
        const MY_CONSTANT  = 1;
    }

    // Dynamic access to 'E_ALL'
    echo constant('i::MY_CONSTANT');

?>

1.2.80.1. Specs

Short name Classes/DynamicConstantCall
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.81. Dynamic Methodcall

Dynamic calls to class methods.
<?php

class x {
    static public function foo() {}
           public function bar() {}
}

$staticmethod = 'foo';
// dynamic static method call to x::foo()
x::$staticmethod();

$method = 'bar';
// dynamic method call to bar()
$object = new x();
$object->$method();

?>

1.2.81.1. Specs

Short name Classes/DynamicMethodCall
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.82. Dynamic New

Dynamic instantiation of classes.
<?php
  $object = new $classname()
?>

.

1.2.82.1. Specs

Short name Classes/DynamicNew
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.83. Dynamic Property

Dynamic access to class property.
<?php

class x {
    static public $foo = 1;
           public $bar = 2;
}

$staticproperty = 'foo';
// dynamic static property call to x::$foo
echo x::${$staticproperty};

$property = 'bar';
// dynamic property call to bar()
$object = new x();
$object->$property = 4;

?>

1.2.83.1. Specs

Short name Classes/DynamicPropertyCall
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.84. Dynamic Self Calls

A class that calls itself dynamically. This may be property or methods.

Calling itself dynamically happens when a class is configured to call various properties (container) or methods.

<?php

class x {
    function foo() {
        $f = 'goo';
        return $this->$f();
    }

    function goo() {
        return rand(1, 10);
    }
}
?>

This rule is mostly useful internally, to side some special situations.

1.2.84.1. Specs

Short name Classes/DynamicSelfCalls
Rulesets none
Exakt since 2.1.1
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.85. Empty Classes

Classes that do no define anything at all. This is probably dead code.

Classes that are directly derived from an exception are omitted.

<?php

//Empty class
class foo extends bar {}

//Not an empty class
class foo2 extends bar {
    const FOO = 2;
}

//Not an empty class, as derived from Exception
class barException extends \Exception {}

?>

1.2.85.1. Suggestions

  • Remove an empty class :it is probably dead code.
  • Add some code to the class to make it concrete.

1.2.85.2. Specs

Short name Classes/EmptyClass
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High
Examples WordPress

1.2.86. Class Should Be Final By Ocramius

‘Make your classes always final, if they implement an interface, and no other public methods are defined’.

When a class should be final, as explained by Ocramius (Marco Pivetta).

<?php

interface i1 {
    function i1() ;
}

// Class should final, as its public methods are in an interface
class finalClass implements i1 {
    // public interface
    function i1 () {}

    // private method
    private function a1 () {}
}

?>

See also When to declare classes final.

1.2.86.1. Specs

Short name Classes/FinalByOcramius
Rulesets Analyze
Exakt since 0.9.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.87. Final Class Usage

List of all final classes being used.

final may be applied to classes and methods.

<?php
class BaseClass {
   public function test() {
       echo 'BaseClass::test() called'.PHP_EOL;
   }

   final public function moreTesting() {
       echo 'BaseClass::moreTesting() called'.PHP_EOL;
   }
}

class ChildClass extends BaseClass {
   public function moreTesting() {
       echo 'ChildClass::moreTesting() called'.PHP_EOL;
   }
}
// Results in Fatal error: Cannot override final method BaseClass::moreTesting()
?>

See also Final Keyword.

1.2.87.1. Specs

Short name Classes/Finalclass
Rulesets ClassReview, LintButWontExec
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.88. Final Methods Usage

List of all final methods being used.

final may be applied to classes and methods.

<?php
class BaseClass {
   public function test() {
       echo 'BaseClass::test() called'.PHP_EOL;
   }

   final public function moreTesting() {
       echo 'BaseClass::moreTesting() called'.PHP_EOL;
   }
}

class ChildClass extends BaseClass {
   public function moreTesting() {
       echo 'ChildClass::moreTesting() called'.PHP_EOL;
   }
}
// Results in Fatal error: Cannot override final method BaseClass::moreTesting()
?>

See also Final Keyword.

1.2.88.1. Specs

Short name Classes/Finalmethod
Rulesets ClassReview, LintButWontExec
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.89. Final Private Methods

PHP’s private methods cannot be overwritten, as they are dedicated to the current class. That way, the final keyword is useless.

PHP 8.0 warns when it finds such a method.

<?php

class foo {
    // Final and private both prevent child classes to overwrite the method
    final private function bar() {}

    // Final and protected (or public) keep this method available, but not overwritable
    final protected function bar() {}
}

?>

See also Final Keyword.

1.2.89.1. Suggestions

  • Remove the final keyword
  • Relax visibility

1.2.89.2. Specs

Short name Classes/FinalPrivate
Rulesets CE, ClassReview, CompatibilityPHP80
Exakt since 2.2.0
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision Very high

1.2.90. Fossilized Method

A method is fossilized when it is overwritten so often that changing a default value, a return type or an argument type is getting difficult.

This happens when a class is extended. When a method is overwritten once, it may be easy to update the signature in two places. The more methods are overwriting a parent method, the more difficult it is to update it.

This analysis counts the number of times a method is overwritten, and report any method that is ovrewritten more than 6 times. This threshold may be configured.

<?php

class x1 {
    // foo1() is never overwritten. It is easy to update.
    function foo1() {}

    // foo7() is overwritten seven times. It is hard to update.
    function foo7() {}
}

// classes x2 to x7, all overwrite foo7();
// Only x2 is presente here.
class x2 extends x1 {
    function foo7() {}
}

?>
Name Default Type Description
fossilizationThreshold 6 integer Minimal number of overwriting methods to consider a method difficult to update.

1.2.90.1. Specs

Short name Classes/FossilizedMethod
Rulesets ClassReview, Typechecks
Exakt since 2.0.6
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.91. Class Has Fluent Interface

Mark a class as such when it contains at least one fluent method. A fluent method is a method that returns $this, for chaining.
<?php

class foo {
    private $count = 0;

    function a() {
        ++$this->count;
        return $this;
    }

    function b() {
        $this->count += 2;
        return $this;
    }

    function c() {
        return $this->count;
    }
}

$bar = new foo();
print $bar->a()
          ->b()
          ->c();

// display 3 (1 + 2).

?>
See also The basics of Fluent interfaces in PHP and
Fluent interface are evil

1.2.91.1. Specs

Short name Classes/HasFluentInterface
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.92. Has Magic Property

The class has defined one of the magic methods.

The magic methods are : __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone() and __debugInfo().

__construct() and __destruct() are omitted here.

<?php

class WithMagic {
    // some more methods, const or properties

    public function __get() {
        // doSomething();
    }
}

?>

See also Property overloading.

1.2.92.1. Specs

Short name Classes/HasMagicProperty
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.93. Hidden Nullable

Argument with default value of null are nullable. Even when the null typehint (PHP 8.0), or the ? operator are not used, setting the default value to null is allowed, and makes the argument nullable.

This doesn’t happen with properties : they must be defined with the nullable type to accept a ``null``value as default value.

This doesn’t happen with constant, which can’t be typehinted.

<?php

// explicit nullable parameter $s
function bar(?string $s = null) {

// implicit nullable parameter $s
function foo(string $s = null) {
    echo $s ?? 'NULL-value';
}

// both display NULL-value
foo();
foo(null);

?>

See also Nullable types and Type declaration.

1.2.93.1. Suggestions

  • Change the default value to a compatible literal : for example, string $s = ''
  • Add the explicit ? nullable operator, or ``null``with PHP 8.0
  • Remove the default value

1.2.93.2. Specs

Short name Classes/HiddenNullable
Rulesets Analyze, ClassReview
Exakt since 2.1.0
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.94. Identical Methods

When the parent class and the child class have the same method, the child might drop it. This reduces code duplication.

Duplicate code in methods is often the results of code evolution, where a method was copied with the hierarchy, but the original wasn’t removed.

This doesn’t apply to private methods, which are reserved for one class.

<?php

class a {
    public function foo() {
        return rand(0, 100);
    }
}

class b extends a {
    public function foo() {
        return rand(0, 100);
    }
}

?>

1.2.94.1. Suggestions

  • Drop the method from the parent class, in particular if only one child uses the method.
  • Drop the method from the child class, in particular if there are several children class
  • Use an abstract method, and make sure every child has its own implementation
  • Modify one of the methods so they are different

1.2.94.2. Specs

Short name Classes/IdenticalMethods
Rulesets none
Exakt since 1.8.2
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision Medium

1.2.95. Immutable Signature

Overwrites makes refactoring a method signature difficult. PHP enforces compatible signature, by checking if arguments have the same type, reference and default values.

In PHP 7.3, typehint had to be the same, or dropped. In PHP 7.4, typehint may be contravariant (arguments), or covariant (returntype).

This analysis may be configured with maxOverwrite. By default, a minimum of 8 overwritten methods is considered difficult to update.

<?php

// Changing any of the four foo() method signature will trigger a PHP warning
class a {
    function foo($a) {}
}

class ab1 extends a {
    // four foo() methods have to be refactored at the same time!
    function foo($ab1) {}
}

class ab2 extends a {
    function foo($ab2) {}
}

class ab3 extends ab1 {
    function foo($abc1) {}
}

?>

When refactoring a method, all the related methodcall may have to be updated too. Adding a type, a default value, or a new argument with default value won’t affect the calls, but only the definitions. Otherwise, calls will also have to be updated.

IDE may help with signature refactoring, such as Refactoring code.

See also Covariance and contravariance (computer science), extends.

Name Default Type Description
maxOverwrite 8 integer Minimal number of method overwrite to consider that any refactor on the method signature is now hard.

1.2.95.1. Specs

Short name Classes/ImmutableSignature
Rulesets CE
Exakt since 1.9.9
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.96. Implemented Methods Are Public

Class methods that are defined in an interface must be public. They cannot be either private, nor protected.

This error is not reported by lint, but is reported at execution time.

<?php

interface i {
    function foo();
}

class X {
    // This method is defined in the interface : it must be public
    protected function foo() {}

    // other methods may be private
    private function bar() {}
}

?>

See also Interfaces and Interfaces - the next level of abstraction.

1.2.96.1. Suggestions

  • Make the implemented method public

1.2.96.2. Specs

Short name Classes/ImplementedMethodsArePublic
Rulesets Analyze
Exakt since 0.11.5
Php Version All
Severity Major
Time To Fix Instant (5 mins)
Precision High

1.2.97. Implement Is For Interface

With class heritage, implements should be used for interfaces, and extends with classes.

PHP defers the implements check until execution : the code in example does lint, but won,t run.

<?php

class x {
    function foo() {}
}

interface y {
    function foo();
}

// Use implements with an interface
class z implements y {}

// Implements is for an interface, not a class
class z implements x {}

?>

1.2.97.1. Suggestions

  • Create an interface from the class, and use it with the implements keyword

1.2.97.2. Specs

Short name Classes/ImplementIsForInterface
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.98. Incompatible Signature Methods

Methods should have the same signature when being overwritten.

The same signatures means the children class must have : + the same name + the same visibility or less restrictive + the same typehint or removed + the same default value or removed + a reference like its parent

This problem emits a fatal error, for abstract methods, or a warning error, for normal methods. Yet, it is difficult to lint, because classes are often stored in different files. As such, PHP do lint each file independently, as unknown parent classes are not checked if not present. Yet, when executing the code, PHP lint the actual code and may encounter a fatal error.

<?php

class a {
    public function foo($a = 1) {}
}

class ab extends a {
    // foo is overloaded and now includes a default value for $a
    public function foo($a) {}
}

?>

See also Object Inheritance.

1.2.98.1. Suggestions

  • Make signatures compatible again

1.2.98.2. Specs

Short name Classes/IncompatibleSignature
Rulesets Analyze, LintButWontExec
Exakt since 1.3.3
Php Version 7.4-
Severity Critical
Time To Fix Quick (30 mins)
Precision High
Examples SuiteCrm

1.2.99. Incompatible Signature Methods With Covariance

Methods should have the compatible signature when being overwritten.

The same signatures means the children class must have : + the same name + the same visibility or less restrictive + the same contravariant typehint or removed + the same covariant return typehint or removed + the same default value or removed + a reference like its parent

This problem emits a fatal error, for abstract methods, or a warning error, for normal methods. Yet, it is difficult to lint, because classes are often stored in different files. As such, PHP do lint each file independently, as unknown parent classes are not checked if not present. Yet, when executing the code, PHP lint the actual code and may encounter a fatal error.

<?php

class a {
    public function foo($a = 1) {}
}

class ab extends a {
    // foo is overloaded and now includes a default value for $a
    public function foo($a) {}
}

?>
See also Object Inheritance,
PHP RFC: Covariant Returns and Contravariant Parameters and Incompatible Signature Methods.

1.2.99.1. Suggestions

  • Make signatures compatible again

1.2.99.2. Specs

Short name Classes/IncompatibleSignature74
Rulesets Analyze
Exakt since 1.3.3
Php Version 7.4+
Severity Critical
Time To Fix Quick (30 mins)
Precision High
Examples SuiteCrm

1.2.100. Instantiating Abstract Class

PHP cannot instantiate an abstract class.

The classes are actually abstract classes, and should be derived into a concrete class to be instantiated.

<?php

abstract class Foo {
    protected $a;
}

class Bar extends Foo {
    protected $b;
}

// instantiating a concrete class.
new Bar();

// instantiating an abstract class.
// In real life, this is not possible also because the definition and the instantiation are in the same file
new Foo();

?>

See also Class Abstraction.

1.2.100.1. Specs

Short name Classes/InstantiatingAbstractClass
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High

1.2.101. Insufficient Property Typehint

The typehint used for a class property doesn’t cover all it usage.

The typehint is insufficient when a undefined method is called, or if members are access while the typehint is an interface.

<?php

class A {
    function a1() {}
}

// PHP 7.4 and more recent
class B {
    private A $a = null;

    function b2() {
        // this method is available in A
        $this->a->a1();
        // this method is NOT available in A
        $this->a->a2();
    }
}

// Supported by all PHP versions
class C {
    private $a = null;

    function __construct(A $a) {
        $this->a = $a;
    }

    function b2() {
        // this method is available in A
        $this->a->a1();
        // this method is NOT available in A
        $this->a->a2();
    }
}

?>

This analysis relies on typehinted properties, as introduced in PHP 7.4. It also relies on typehinted assignations at construct time : the typehint of the assigned argument will be used as the property typehint. Getters and setters are not considered here.

1.2.101.1. Suggestions

  • Change the typehint to match the actual usage of the object in the class.

1.2.101.2. Specs

Short name Classes/InsufficientPropertyTypehint
Rulesets ClassReview
Exakt since 2.0.2
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.102. Integer As Property

It is backward incompatible to use integers are property names. This feature was introduced in PHP 7.2.

If the code must be compatible with previous versions, avoid casting arrays to object.

<?php

// array to object
$arr = [0 => 1];
$obj = (object) $arr;
var_dump(
    $obj,
    $obj->{'0'}, // PHP 7.2+ accessible
    $obj->{0} // PHP 7.2+ accessible

    $obj->{'b'}, // always been accessible
);
?>

See also PHP RFC: Convert numeric keys in object/array casts.

1.2.102.1. Specs

Short name Classes/IntegerAsProperty
Rulesets CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56, CompatibilityPHP70, CompatibilityPHP71
Exakt since 1.0.4
Php Version 7.2+
Severity Major
Time To Fix Slow (1 hour)
Precision High

1.2.103. Is A PHP Magic Property

Mark properties usage when they are actually a magic call.
<?php

class magicProperty {
    public $b;

    function __get($name) {
        // do something with the value
    }

    function foo() {
        $this->a;
        $this->b;
    }
}

?>

See also Magic Methods.

1.2.103.1. Specs

Short name Classes/IsaMagicProperty
Rulesets CE
Exakt since 0.12.17
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.104. Is An Extension Class

Those classes belongs to a PHP Extensions.
<?php

// This is a native PHP class
$o = new Stdclass();

// This is not a native PHP class
$o = new Elephpant();

?>

1.2.104.1. Specs

Short name Classes/IsExtClass
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.105. Is Interface Method

Mark a method as part of an interface that the current class implements.
<?php

interface i {
    function i20();
}

class x implements i {
    // This is an interface method
    function i20() {}

    // This is not an interface method
    function x20() {}
}

?>

1.2.105.1. Specs

Short name Classes/IsInterfaceMethod
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.106. Is Not Class Family

Mark a static method call as inside the family of classes. Children are not considered here.
<?php

class a {
    function familyMethod() {}
}

classs b {
    function foo() {
        self::familyMethod(); // This is a call to a family method
        b::notAFamilyMethod(); // This is a call to a method of a class outside the family
    }
}
?>

1.2.106.1. Specs

Short name Classes/IsNotFamily
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.107. Is Upper Family

Does the static call is made within the current hierarchy of class, or, is it made in the class, in the children or outside.

This applies to static methodcalls, property accesses and class constants.

<?php

class AAA            { function inAAA() {} }   // upper family : grand-parent
class AA extends AAA { function inAA()  {} }   // upper family : parent
class A  extends AA  { function inA()  {} }    // current family
class B  extends A   { function inB()  {} }    // lower family
class C              { function inC()  {} }    // outside family

?>

1.2.107.1. Specs

Short name Classes/IsUpperFamily
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.108. Locally Unused Property

Those properties are defined in a class, and this class doesn’t have any method that makes use of them.

While this is syntactically correct, it is unusual that defined resources are used in a child class. It may be worth moving the definition to another class, or to move accessing methods to the class.

<?php

class foo {
    public $unused, $used;// property $unused is never used in this class

    function bar() {
        $this->used++; // property $used is used in this method
    }
}

class foofoo extends foo {
    function bar() {
        $this->unused++; // property $unused is used in this method, but defined in the parent class
    }
}

?>

1.2.108.1. Suggestions

  • Move the property definition to the child classes
  • Move some of the child method, using the property, to the parent class

1.2.108.2. Specs

Short name Classes/LocallyUnusedProperty
Rulesets Dead code
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.109. Locally Used Property

Properties that are used in the class where they are defined.
<?php

class foo {
    public $unused, $used;// property $unused is never used in this class

    function bar() {
        $this->used++; // property $used is used in this method
    }
}

$foo = new Foo();
$foo->unused = 'here'; // property $unused is used outside the class definition
?>

1.2.109.1. Specs

Short name Classes/LocallyUsedProperty
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.110. Magic Methods

List of PHP magic methods being used. The magic methods are

__call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone() and __debugInfo().

__construct and __destruct are omitted here, as they are routinely used to create and destroy objects.

<?php

class foo{
    // PHP Magic method, called when cloning an object.
    function __clone() {}
}
?>

See also Magic Method.

1.2.110.1. Specs

Short name Classes/MagicMethod
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.111. Magic Properties

List of magic properties used in the code

1.2.111.1. Suggestions

1.2.111.2. Specs

Short name Classes/MagicProperties
Rulesets none
Exakt since 1.9.5
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.112. Assign Default To Properties

Properties may be assigned default values at declaration time. Such values may be later modified, if needed.
<?php

class foo {
    private $propertyWithDefault = 1;
    private $propertyWithoutDefault;
    private $propertyThatCantHaveDefault;

    public function __construct() {
        // Skip this extra line, and give the default value above
        $this->propertyWithoutDefault = 1;

        // Static expressions are available to set up simple computation at definition time.
        $this->propertyWithoutDefault = OtherClass::CONSTANT + 1;

        // Arrays, just like scalars, may be set at definition time
        $this->propertyWithoutDefault = [1,2,3];

        // Objects or resources can't be made default. That is OK.
        $this->propertyThatCantHaveDefault = fopen('/path/to/file.txt');
        $this->propertyThatCantHaveDefault = new Fileinfo();
    }
}

?>

Default values will save some instructions in the constructor, and makes the value obvious in the code.

1.2.112.1. Suggestions

  • Add a default value whenever possible. This is easy for scalars, and array()

1.2.112.2. Specs

Short name Classes/MakeDefault
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Instant (5 mins)
Precision High
ClearPHP use-properties-default-values
Examples LiveZilla, phpMyAdmin

1.2.113. Make Global A Property

Calling global (or $GLOBALS) in methods is slower and less testable than setting the global to a property, and using this property.

Using properties is slightly faster than calling global or $GLOBALS, though the gain is not important.

Setting the property in the constructor (or in a factory), makes the class easier to test, as there is now a single point of configuration.

<?php

// Wrong way
class fooBad {
    function x() {
        global $a;
        $a->do();
        // Or $GLOBALS['a']->do();
    }
}

class fooGood {
    private $bar = null;

    function __construct() {
        global $bar;
        $this->bar = $bar;
        // Even better, do this via arguments
    }

    function x() {
        $this->a->do();
    }
}

?>

1.2.113.1. Suggestions

  • Avoid using global variables, and use properties instead
  • Remove the usage of these global variables

1.2.113.2. Specs

Short name Classes/MakeGlobalAProperty
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.114. Make Magic Concrete

Speed up execution by replacing magic calls by concrete properties.

Magic properties are managed dynamically, with __get``and ``__set. They replace property access by a methodcall, and they are much slower than the first.

When a property name is getting used more often, it is worth creating a concrete property, and skip the method call. The threshold for ‘magicMemberUsage’ is 1, by default.

<?php

class x {
    private $values = array('a' => 1,
                            'b' => 2);

    function __get($name) {
        return $this->values[$name] ?? '';
    }
}

$x = new x();
// Access to 'a' is repeated in the code, at least 'magicMemberUsage' time (cf configuration below)
echo $x->a;

?>

See also Memoize MagicCall.

1.2.114.1. Suggestions

  • Make frequently used properties concrete; keep the highly dynamic as magic
Name Default Type Description
magicMemberUsage 1 integer Minimal number of magic member usage across the code, to trigger a concrete property.

1.2.114.2. Specs

Short name Classes/MakeMagicConcrete
Rulesets Performances
Exakt since 1.8.3
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.115. Method Is Overwritten

This marks an method that is overwritten in a child class.
<?php

class A {
    function intactMethodA() {}         // Not overwritten in any children
    function overwrittenMethodInAA() {} // overwritten in AA
}

class AA extends A {
    function intactMethodAA() {}        // Not overwritten, because no extends
    function overwrittenMethodInAA() {} // Not overwritten, because no extends
}

?>

1.2.115.1. Specs

Short name Classes/MethodIsOverwritten
Rulesets none
Exakt since 0.10.9
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.116. Method Signature Must Be Compatible

Make sure methods signature are compatible.

PHP generates the infamous Fatal error at execution : Declaration of FooParent\:\:Bar() must be compatible with FooChildren\:\:Bar()

<?php

class x {
    function xa() {}
}

class xxx extends xx {
    function xa($a) {}
}

?>

1.2.116.1. Suggestions

  • Fix the child class method() signature.
  • Fix the parent class method() signature, after checking that it won’t affect the other children.

1.2.116.2. Specs

Short name Classes/MethodSignatureMustBeCompatible
Rulesets Analyze, LintButWontExec
Exakt since 1.2.9
Php Version All
Severity Critical
Time To Fix Quick (30 mins)
Precision High

1.2.117. Method Used Below

Mark methods that are used in children classes.
<?php

class foo {
    // This method is used in children
    protected function protectedMethod() {}

    // This method is not used in children
    protected function localProtectedMethod() {}

    private function foobar() {
        // protectedMethod is used here, but defined in parent
        $this->localProtectedMethod();
    }
}

class foofoo extends foo {
    private function bar() {
        // protectedMethod is used here, but defined in parent
        $this->protectedMethod();
    }
}

?>

This doesn’t mark the current class, nor the (grand-)`parent <https://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php>`_ ones.

1.2.117.1. Specs

Short name Classes/MethodUsedBelow
Rulesets none
Exakt since 0.12.11
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.118. Mismatch Properties Typehints

Properties must match within the same family.

When a property is declared both in a parent class, and a child class, they must have the same type. The same type includes a possible null value.

This doesn’t apply to private properties, which are only visible locally.

<?php

// property $p is declared as an object of type a
class x {
    protected A $p;
}

// property $p is declared again, this time without a type
class a extends x {
    protected $p;
}
?>

This code will lint, but not execute.

1.2.118.1. Suggestions

  • Remove some of the property declarations, and only keep it in the highest ranking parent
  • Match the typehints of the property declarations
  • Make the properties private
  • Remove the child class (or the parent class)

1.2.118.2. Specs

Short name Classes/MismatchProperties
Rulesets Analyze, ClassReview, LintButWontExec
Exakt since 2.1.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.119. Missing Abstract Method

Abstract methods must have a non-abstract version for the class to be complete. A class that is missing one abstract definition cannot be instantiated.
<?php

// This is a valid definition
class b extends a {
    function foo() {}
    function bar() {}
}

// This compiles, but will emit a fatal error if instantiated
class c extends a {
    function bar() {}
}

// This illustration lint but doesn't run.
// moving this class at the beginning of the code will make lint fail
abstract class a {
    abstract function foo() ;
}

?>

See also Classes Abstraction.

1.2.119.1. Suggestions

  • Implement the missing methods
  • Remove the partially implemented class
  • Mark the partially implemented class abstract

1.2.119.2. Specs

Short name Classes/MissingAbstractMethod
Rulesets Analyze, ClassReview
Exakt since 2.1.0
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.120. Multiple Classes In One File

It is regarded as a bad practice to store several classes in the same file. This is usually done to make life of __autoload() easier.

It is often unexpected to find class foo in the bar.php file. This is also the case for interfaces and traits.

<?php

// three classes in the same file
class foo {}
class bar {}
class foobar{}

?>

One good reason to have multiple classes in one file is to reduce include time by providing everything into one nice include.

See also Is it a bad practice to have multiple classes in the same file?.

1.2.120.1. Suggestions

  • Split the file into smaller files, one for each class

1.2.120.2. Specs

Short name Classes/MultipleClassesInFile
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.121. Multiple Class Declarations

It is possible to declare several times the same class in the code. PHP will not mention it until execution time, since declarations may be conditional.
<?php

$a = 1;

// Conditional declaration
if ($a == 1) {
    class foo {
        function method() { echo 'class 1';}
    }
} else {
    class foo {
        function method() { echo 'class 2';}
    }
}

(new foo())->method();
?>

It is recommended to avoid declaring several times the same class in the code. The best practice is to separate them with namespaces, they are for here for that purpose. In case those two classes are to be used interchangeably, the best is to use an abstract class or an interface.

1.2.121.1. Suggestions

  • Store classes with different names in different namespaces
  • Change the name of the classes and give them a common interface to allow from common behavior

1.2.121.2. Specs

Short name Classes/MultipleDeclarations
Rulesets Analyze, CE, CI-checks
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High

1.2.122. Multiple Property Declaration On One Line

Multiple properties are defined on the same line. They could be defined independantly, on separate expressions.

Keeping properties separate helps documenting and refactoring them independantly.

<?php

// multiple definition on one expression
class point {
    private $x, $y, $z;

    // more code
}

// one line, one definition
class point2 {
    private $x;

    private $y;

    private $z;

    // more code
}

?>

1.2.122.1. Suggestions

  • Split the definitions to one by line

1.2.122.2. Specs

Short name Classes/MultiplePropertyDeclarationOnOneLine
Rulesets none
Exakt since 2.2.2
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision Very high

1.2.123. Multiple Identical Trait Or Interface

There is no need to use the same trait, or implements the same interface more than once.

Up to PHP 7.1 (at least), this doesn’t raise any warning. Traits are only imported once, and interfaces may be implemented as many times as wanted.

<?php

class foo {
    use t3,t3,t3;
}

class bar implements i,i,i {

}

?>

1.2.123.1. Suggestions

  • Remove the duplicate trait or interfaces

1.2.123.2. Specs

Short name Classes/MultipleTraitOrInterface
Rulesets Analyze, CE, CI-checks
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Instant (5 mins)
Precision High

1.2.124. Classes Mutually Extending Each Other

Those classes are extending each other, creating an extension loop. PHP will yield a fatal error at running time, even if it is compiling the code.
<?php

// This code is lintable but won't run
class Foo extends Bar { }
class Bar extends Foo { }

// The loop may be quite large
class Foo extends Bar { }
class Bar extends Bar2 { }
class Bar2 extends Foo { }

?>

1.2.124.1. Specs

Short name Classes/MutualExtension
Rulesets ClassReview, LintButWontExec
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High

1.2.125. New On Functioncall Or Identifier

Object instantiation with new works with or without arguments. Both are valid in PHP.

The analyzed code has less than 10% of one of the two forms : for consistency reasons, it is recommended to make them all the same.

<?php

$a = new stdClass();

// Parenthesis are used when arguments are compulsory
$mysql = new MySQLI($host, $user, $pass);

// Parenthesis are omitted when no arguments are available
// That also makes the instantiation look different
$b = new stdClass;

?>

1.2.125.1. Specs

Short name Classes/NewOnFunctioncallOrIdentifier
Rulesets none
Exakt since 0.9.8
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.126. No Magic Method With Array

Magic method __set() doesn’t work for array syntax.

When overloading properties, they can only be used for scalar values, excluding arrays. Under the hood, PHP uses __get() to reach for the name of the property, and doesn’t recognize the following index as an array. It yields an error : Indirect modification of overloaded property.

<?php

class c {
    private $a;
    private $o = array();

    function __get($name) {
        return $this->o[$name];
    }

    function foo() {
        // property b doesn't exists
        $this->b['a'] = 3;

        print_r($this);
    }

    // This method has no impact on the issue
    function __set($name, $value) {
        $this->o[$name] = $value;
    }
}

$c = new c();
$c->foo();

?>

It is possible to use the array syntax with a magic property : by making the __get returns an array, the syntax will actually extract the expected item in the array.

This is not reported by linting.

In this analysis, only properties that are found to be magic are reported. For example, using the b property outside the class scope is not reported, as it would yield too many false-positives.

See also Overload.

1.2.126.1. Suggestions

  • Use a distinct method to append a new value to that property
  • Assign the whole array, and not just one of its elements

1.2.126.2. Specs

Short name Classes/NoMagicWithArray
Rulesets Analyze, CE, CI-checks, LintButWontExec
Exakt since 0.12.4
Php Version All
Severity Major
Time To Fix Slow (1 hour)
Precision Medium

1.2.127. Non Nullable Getters

A getter needs to be nullable when a property is injected.

In particular, if the injection happens with a separate method, there is a time where the object is not consistent, and the property holds a default non-object value.

<?php

class Consistent {
    private $db = null;

    function __construct(Db $db) {
        $this->db = $db;
        // Object is immediately consistent
    }

    // Db might be null
    function getDb() {
        return $this->db;
    }
}

class Inconsistent {
    private $db = null;

    function __construct() {
        // No initialisation
    }

    // This might be called on time, or not
    // This typehint cannot be nullable, nor use null as default
    function setDb(DB $db) {
        return $this->db;
    }

    // Db might be null
    function getDb() {
        return $this->db;
    }
}
?>

1.2.127.1. Suggestions

  • Remove the nullable option and the tests on null.

1.2.127.2. Specs

Short name Classes/NonNullableSetters
Rulesets Analyze, ClassReview
Exakt since 1.9.6
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.128. Forgotten Visibility

Some classes elements (property, method, constant) are missing their explicit visibility.

By default, it is public. It should at least be mentioned as public, or may be reviewed as protected or private.

Class constants support also visibility since PHP 7.1.

final, static and abstract are not counted as visibility. Only public, private and protected. The PHP 4 var keyword is counted as undefined.

Traits, classes and interfaces are checked.

<?php

// Explicit visibility
class X {
    protected sconst NO_VISIBILITY_CONST = 1; // For PHP 7.2 and later

    private $noVisibilityProperty = 2;

    public function Method() {}
}

// Missing visibility
class X {
    const NO_VISIBILITY_CONST = 1; // For PHP 7.2 and later

    var $noVisibilityProperty = 2; // Only with var

    function NoVisibilityForMethod() {}
}

?>

See also Visibility and Understanding The Concept Of Visibility In Object Oriented PHP.

1.2.128.1. Suggestions

  • Always add explicit visibility to methods and constants in a class
  • Always add explicit visibility to properties in a class, after PHP 7.4

1.2.128.2. Specs

Short name Classes/NonPpp
Rulesets Analyze, CE, CI-checks
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Instant (5 mins)
Precision High
ClearPHP always-have-visibility
Examples FuelCMS, LiveZilla

1.2.129. Non Static Methods Called In A Static

Static methods have to be declared as such (using the static keyword). Then, one may call them without instantiating the object.

PHP 7.0, and more recent versions, yield a deprecated error : Non-`static <https://www.php.net/manual/en/language.oop5.static.php>`_ method A\:\:B() should not be called statically.

PHP 5 and older doesn’t check that a method is static or not : at any point, the code may call one method statically.

<?php
    class x {
        static public function sm( ) { echo __METHOD__.\n; }
        public public sm( ) { echo __METHOD__.\n; }
    }

    x::sm( ); // echo x::sm

    // Dynamic call
    ['x', 'sm']();
    [\x::class, 'sm']();

    $s = 'x::sm';
    $s();

?>

It is a bad idea to call non-static method statically. Such method may make use of special variable $this, which will be undefined. PHP will not check those calls at compile time, nor at running time.

It is recommended to update this situation : make the method actually static, or use it only in object context.

Note that this analysis reports all static method call made on a non-static method, even within the same class or class hierarchy. PHP silently accepts static call to any in-family method.

<?php
    class x {
        public function foo( ) { self::bar() }
        public function bar( ) { echo __METHOD__.\n; }
    }
?>

See also Static Keyword <https://www.php.net/manual/en/language.oop5.`static.php>`_.

1.2.129.1. Suggestions

  • Call the method the correct way
  • Define the method as static

1.2.129.2. Specs

Short name Classes/NonStaticMethodsCalledStatic
Rulesets Analyze, CE, CI-checks, CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision Medium
Examples Dolphin, Magento

1.2.130. Class Without Parent

Classes should not refer to parent when it is not extending another class.

In PHP 7.4, it is a Deprecated warning. In PHP 7.3, it was a Fatal error, when the code was finally executed.

<?php

class x {
    function foo() {
        parent::foo();
    }
}
?>

1.2.130.1. Suggestions

  • Update the class and make it extends another class
  • Change the parent mention with a fully qualified name
  • Remove the call to the parent altogether

1.2.130.2. Specs

Short name Classes/NoParent
Rulesets Analyze, CE, CI-checks, ClassReview
Exakt since 1.9.0
Php Version 7.4-
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.131. self, parent, static Outside Class

self, parent and static should be called inside a class or trait. PHP lint won’t report those situations.

self, parent and static may be used in a trait : their actual value will be only known at execution time, when the trait is used.

<?php
// In the examples, self, parent and static may be used interchangeably

// This raises a Fatal error
//Fatal error: Uncaught Error: Cannot access static:: when no class scope is active
new static();

// static calls
echo self::CONSTANTE;
echo self::$property;
echo self::method();

// as a type hint
function foo(static $x) {
    doSomething();
}

// as a instanceof
if ($x instanceof static) {
    doSomething();
}

?>

Such syntax problem is only revealed at execution time : PHP raises a Fatal error.

The origin of the problem is usually a method that was moved outside a class, at least temporarily.

See also Scope Resolution Operator (::).

1.2.131.1. Specs

Short name Classes/NoPSSOutsideClass
Rulesets Analyze, LintButWontExec
Exakt since 0.10.3
Php Version All
Severity Major
Time To Fix Slow (1 hour)
Precision High

1.2.132. No Public Access

The properties below are declared with public access, but are never used publicly. They can be made protected or private.
<?php

class foo {
    public $bar = 1;            // Public, and used in public space
    public $neverInPublic = 3;  // Public, but never used in outside the class

    function bar() {
        $neverInPublic++;
    }
}

$x = new foo();
$x->bar = 3;
$x->bar();

?>

1.2.132.1. Specs

Short name Classes/NoPublicAccess
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.133. Normal Methods

Spot normal Methods.
<?php

class foo{
    // Normal method
    private function bar() {}

    // Static method
    private static function barbar() {}
}

?>

1.2.133.1. Specs

Short name Classes/NormalMethods
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.134. No Self Referencing Constant

It is not possible to use a constant to define itself in a class. It yields a fatal error at runtime.

The PHP error reads : Cannot declare `self <https://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php>`_-referencing constant '`self <https://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php>`_\:\:C2'. Unlike PHP which is self-referencing, self referencing variables can’t have a value : just don’t use that.

<?php
    class a {
        const C1 = 1;         // fully defined constant
        const C2 = self::C2;  // self referencing constant
        const C3 = a::C3 + 2; // self referencing constant
    }
?>

The code may access an already declared constant with self or with its class name.

<?php
    class a {
        const C1 = 1;
        const C2 = a::C1;
    }
?>

This error is not detected by linting. It is only detected at instantiation time : if the class is not used, it won’t appear.

1.2.134.1. Suggestions

  • Give a literal value to this constant
  • Give a constant value to this constant : other class constants or constant are allowed here.

1.2.134.2. Specs

Short name Classes/NoSelfReferencingConstant
Rulesets Analyze, ClassReview, LintButWontExec
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.135. Null On New

Until PHP 7, some classes instantiation could yield null, instead of throwing an exception.

After issuing a ‘new’ with those classes, it was important to check if the returned object were null or not. No exception were thrown.

<?php

// Example extracted from the wiki below
$mf = new MessageFormatter('en_US', '{this was made intentionally incorrect}');
if ($mf === null) {
    echo 'Surprise!';
}

?>

This inconsistency has been cleaned in PHP 7 : see See Internal Constructor Behavior

See also PHP RFC: Constructor behaviour of internal classes.

1.2.135.1. Suggestions

  • Remove the check on null after a new instantiation

1.2.135.2. Specs

Short name Classes/NullOnNew
Rulesets CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56
Exakt since 0.8.4
Php Version 7.0-
Severity Major
Time To Fix Instant (5 mins)
Precision High

1.2.136. Old Style Constructor

PHP classes used to have the method bearing the same name as the class acts as the constructor. That was PHP 4, and early PHP 5.

The manual issues a warning about this syntax : Old style constructors are DEPRECATED in PHP 7.0, and will be removed in a future version. You should always use `__construct() <https://www.php.net/manual/en/language.oop5.decon.php>`_ in new code.

<?php

namespace {
    // Global namespace is important
    class foo {
        function foo() {
            // This acts as the old-style constructor, and is reported by PHP
        }
    }

    class bar {
        function __construct() { }
        function bar() {
            // This doesn't act as constructor, as bar has a __construct() method
        }
    }
}

namespace Foo\Bar{
    class foo {
        function foo() {
            // This doesn't act as constructor, as bar is not in the global namespace
        }
    }
}

?>

This is no more the case in PHP 5, which relies on __construct() to do so. Having this old style constructor may bring in confusion, unless you are also supporting old time PHP 4.

Note that classes with methods bearing the class name, but inside a namespace are not following this convention, as this is not breaking backward compatibility. Those are excluded from the analyze.

See also Constructors and Destructors.

1.2.136.1. Suggestions

  • Remove old style constructor and make it __construct()
  • Remove old libraries and use a modern component

1.2.136.2. Specs

Short name Classes/OldStyleConstructor
Rulesets Analyze, CE, CompatibilityPHP80
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High
ClearPHP no-php4-class-syntax

1.2.137. Var Keyword

Var was used in PHP 4 to mark properties as public. Nowadays, new keywords are available : public, protected, private. Var is equivalent to public.

It is recommended to avoid using var, and explicitly use the new keywords.

<?php

class foo {
    public $bar = 1;
    // Avoid var
    //var $bar = 1;
}

?>

See also Visibility.

1.2.137.1. Suggestions

  • It is recommended to avoid using var, and explicitly use the new keywords : private, protected, public

1.2.137.2. Specs

Short name Classes/OldStyleVar
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High
ClearPHP no-php4-class-syntax
Examples xataface

1.2.138. One Object Operator Per Line

Avoid using more than one operator -> per line, to prevent information overload.
<?php

// Spread operators on multiple lines
$object->firstMethodCall()
       ->property
       ->secondMethodCall();

// This is not readable
$object->firstMethodCall()->property->secondMethodCall();

// This is OK, as objects are different.
$a2->b2($c2->d2, $e2->f2);

?>

1.2.138.1. Specs

Short name Classes/OneObjectOperatorPerLine
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.139. Only Static Methods

Marks a class that has only static methods.

1.2.139.1. Specs

Short name Classes/OnlyStaticMethods
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.140. Order Of Declaration

The order used to declare members and methods has a great impact on readability and maintenance. However, practices varies greatly. As usual, being consistent is the most important and useful.

The suggested order is the following : traits, constants, properties, methods. Optional characteristics, like final, static… are not specified. Special methods names are not specified.

<?php

class x {
    use traits;

    const CONSTANTS = 1;
    const CONSTANTS2 = 1;
    const CONSTANTS3 = 1;

    private $property = 2;
    private $property2 = 2;
    private $property3 = 2;

    public function foo() {}
    public function foo2() {}
    public function foo3() {}
    public function foo4() {}
}

?>

1.2.140.1. Suggestions

  • Always declare class elements (traits, constants, properties, methods) in the same order.

1.2.140.2. Specs

Short name Classes/OrderOfDeclaration
Rulesets none
Exakt since 0.11.7
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision Medium

1.2.141. Overwritten Class Const

Those class constants are overwritten in a parent class. This may lead to confusion, as the value of the constant may change depending on the way it is called.
<?php

class foo {
    const C = 1;
}

class bar extends foo {
    const C = 2;

    function x() {
        // depending on the access to C, value is different.
        print self::C.' '.static::C.' '.parent::C;
    }
}

?>

1.2.141.1. Specs

Short name Classes/OverwrittenConst
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Slow (1 hour)
Precision High

1.2.142. Parent First

When calling parent constructor, always put it first in the __construct method. It ensures the parent is correctly build before the child start using values.
<?php

class father {
    protected $name = null;

    function __construct() {
        $this->name = init();
    }
}

class goodSon {
    function __construct() {
        // parent is build immediately,
        parent::__construct();
        echo my name is.$this->name;
    }
}

class badSon {
    function __construct() {
        // This will fail.
        echo my name is.$this->name;

        // parent is build later,
        parent::__construct();
    }
}

?>

This analysis doesn’t apply to Exceptions.

1.2.142.1. Suggestions

  • Use parent\:\:__construct as the first call in the constructor.

1.2.142.2. Specs

Short name Classes/ParentFirst
Rulesets Analyze, Suggestions
Exakt since 1.0.5
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High
Examples shopware, PrestaShop

1.2.143. Properties Declaration Consistence

Properties may be declared all at once, or one by one.

The analyzed code has less than 10% of one of them : for consistency reasons, it is recommended to make them all the same.

It happens that choosing unique declarations or multiple depends on coding style and files.

<?php

class x {
    // Some declarations are made by batch
    private $a1 = 1,
            $a2 = 2;
    public $c = 1, $c2 = 2, $c4 = 3;

    // Most declarations are made one by one
    protected $b = 1;
    protected $b1 = 1;
    protected $b2 = 1;
    protected $b3 = 1;
    protected $b4 = 1;
    protected $b5 = 1;
    protected $b6 = 1;
    protected $b7 = 1;
    protected $b8 = 1;
    protected $b9 = 1;
    protected $b10 = 1;
    protected $b11 = 1;
    protected $b12 = 1;
    protected $b13 = 1;
    protected $b14 = 1;
    protected $b15 = 1;
    protected $b16 = 1;
    protected $b17 = 1;
    protected $b18 = 1;
    protected $b19 = 1;

}
?>

See also Properties.

1.2.143.1. Specs

Short name Classes/PPPDeclarationStyle
Rulesets none
Exakt since 1.2.1
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.144. Property Could Be Local

A property only used in one method may be turned into a local variable.

Public an protected properties are omitted here : they may be modified somewhere else, in the code. This analysis may be upgraded to support those properties, when tracking of such properties becomes available.

Classes where only one non-magic method is available are omitted.

Traits with private properties are processed the same way.

<?php

class x {
    private $foo = 1;

    // Magic method, and constructor in particular, are omitted.
    function __construct($foo) {
        $this->foo = $foo;
    }

    function bar() {
        $this->foo++;

        return $this->foo;
    }

    function barbar() {}
}

?>

1.2.144.1. Suggestions

  • Remove the property and make it an argument in the method
  • Use that property elsewhere

1.2.144.2. Specs

Short name Classes/PropertyCouldBeLocal
Rulesets Analyze, ClassReview
Exakt since 1.1.7
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High
Examples Mautic, Typo3

1.2.145. Property Names

Variables are used in property definitions, when they are located in a class.
<?php

static $x; // not a property, a static variable

class foo {
    static $x; // now, this is a static property
    public $y, $z = 1; // normal properties

    public function bar() {
        static $x; // again, a static variable
    }
}

?>

See also Properties.

1.2.145.1. Specs

Short name Classes/PropertyDefinition
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.146. Never Used Properties

Properties that are never used. They are defined in a class or a trait, but they never actually used.

Properties are considered used when they are used locally, in the same class as their definition, or in a parent class : a parent class is always included with the current class.

On the other hand, properties which are defined in a class, but only used in children classes is considered unused, since children may also avoid using it.

<?php

class foo {
    public $usedProperty = 1;

    // Never used anywhere
    public $unusedProperty = 2;

    function bar() {
        // Used internally
        ++$this->usedProperty;
    }
}

class foo2  extends foo {
    function bar2() {
        // Used in child class
        ++$this->usedProperty;
    }
}

// Used externally
++$this->usedProperty;

?>

1.2.146.1. Suggestions

  • Drop unused properties
  • Change the name of the unused properties
  • Move the properties to children classes
  • Find usage for unused properties

1.2.146.2. Specs

Short name Classes/PropertyNeverUsed
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High
Examples WordPress

1.2.147. Property Used Above

Property used in the parent classes. If the definition of the property is in the child class, then the parent should not know about it and make usage of it.

It may also be used in the current class, or its children, though this is not reported by this analyzer.

<?php

class A {
    public function foo() {
        $this->pb++;
    }
}

class B extends A {
    protected $pb = 0;       // property     used above
    protected $pb2 = 0;      // property NOT used above
}

?>

See also `Classes/PropertyUsedBelow`_.

1.2.147.1. Suggestions

  • Move the definition of the property to the upper class
  • Move the usage of the property to the lower class

1.2.147.2. Specs

Short name Classes/PropertyUsedAbove
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision Medium

1.2.148. Property Used Below

Mark properties that are used in children classes.
<?php

class foo {
    // This property is used in children
    protected protectedProperty = 1;

    // This property is not used in children
    protected localProtectedProperty = 1;

    private function foobar() {
        // protectedProperty is used here, but defined in parent
        $this->localProtectedProperty = 3;
    }
}

class foofoo extends foo {
    private function bar() {
        // protectedProperty is used here, but defined in parent
        $this->protectedProperty = 3;
    }
}

?>

This doesn’t mark the current class, nor the (grand-)`parent <https://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php>`_ ones.

1.2.148.1. Specs

Short name Classes/PropertyUsedBelow
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision Medium

1.2.149. Property Used In One Method Only

Properties should be used in several methods. When a property is used in only one method, this should have be of another shape.

Properties used in one method only may be used several times, and read only. This may be a class constant. Such properties are meant to be overwritten by an extending class, and that’s possible with class constants.

Properties that read and written may be converted into a variable, static to the method. This way, they are kept close to the method, and do not pollute the object’s properties.

<?php

class foo {
    private $once = 1;
    const ONCE = 1;
    private $counter = 0;

    function bar() {
        // $this->once is never used anywhere else.
        someFunction($this->once);
        someFunction(self::ONCE);   // Make clear that it is a
    }

    function bar2() {
        static $localCounter = 0;
        $this->counter++;

        // $this->once is only used here, for distinguising calls to someFunction2
        if ($this->counter > 10) { // $this->counter is used only in bar2, but it may be used several times
            return false;
        }
        someFunction2($this->counter);

        // $localCounter keeps track for all the calls
        if ($localCounter > 10) {
            return false;
        }
        someFunction2($localCounter);
    }
}

?>

Note : properties used only once are not returned by this analysis. They are omitted, and are available in the analysis Used Once Property.

1.2.149.1. Suggestions

  • Drop the property, and inline the value
  • Drop the property, and make the property a local variable
  • Use the property in another method

1.2.149.2. Specs

Short name Classes/PropertyUsedInOneMethodOnly
Rulesets Analyze
Exakt since 0.10.3
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High
Examples Contao

1.2.150. Internally Used Properties

Properties that are used internally.
<?php

class x {
    public $internallyUsedProperty = 1;
    public $externallyUsedProperty = 1;
    public $alsoExternallyUsedProperty = 1;

    function foo() {
        $this->internallyUsedProperty = 2;
    }
}

class y extends x {
    function bar() {
        $this->externallyUsedProperty = 3;
    }
}

$X = new x();
$X->alsoExternallyUsedProperty = 3;

?>

1.2.150.1. Specs

Short name Classes/PropertyUsedInternally
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Instant (5 mins)
Precision High

1.2.151. Parent, Static Or Self Outside Class

Parent, static and self keywords must be used within a class or a trait. They make no sens outside a class or trait scope, as self and static refers to the current class and parent refers to one of parent above.

PHP 7.0 and later detect their usage at compile time, and emits a fatal error.

<?php

class x {
    const Y = 1;

    function foo() {
        // self is \x
        echo self::Y;
    }
}

const Z = 1;
// This lint but won't anymore
echo self::Z;

?>

Static may be used in a function or a closure, but not globally.

1.2.151.1. Specs

Short name Classes/PssWithoutClass
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High

1.2.152. Raised Access Level

A property’s visibility may be lowered, but not raised.

This error may be detected when the classes are all in the same file : then, PHP reports the problem. However, when the classes are separated in different files, as it is customary, PHP won’t check this at linting time, yielding a fatal error at execution time.

First file.

<?php

class Foo {
    public $publicProperty;
    protected $protectedProperty;
    private $privateProperty;
}
?>

Second file.

<?php

class Bar extends Foo {
    private $publicProperty;
    private $protectedProperty;
    private $privateProperty;   // This one is OK
}
?>

See also Visibility and Understanding the concept of visibility in object oriented php.

1.2.152.1. Suggestions

  • Lower the visibility in the child class
  • Raise the visibility in the parent class

1.2.152.2. Specs

Short name Classes/RaisedAccessLevel
Rulesets ClassReview, LintButWontExec
Exakt since 0.10.0
Php Version All
Severity Critical
Time To Fix Quick (30 mins)
Precision High

1.2.153. Redefined Class Constants

Redefined class constants.

Class constants may be redefined, though it is prone to errors when using them, as it is now crucial to use the right class name to access the right value.

<?php

class a {
    const A = 1;
}

class b extends a {
    const A = 2;
}

class c extends c { }

echo a::A, ' ', b::A, ' ', c::A;
// 1 2 2

?>

It is recommended to use distinct names.

1.2.153.1. Specs

Short name Classes/RedefinedConstants
Rulesets Analyze, CE, CI-checks
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.154. Redefined Default

Classes allows properties to be set with a default value. When those properties get, unconditionally, another value at constructor time, then one of the default value are useless. One of those definition should go : it is better to define properties outside the constructor.
<?php

class foo {
    public $redefined = 1;

    public function __construct( ) {
        $this->redefined = 2;
    }
}

?>

1.2.154.1. Suggestions

  • Move the default assignation to the property definition
  • Drop the reassignation in the constructor

1.2.154.2. Specs

Short name Classes/RedefinedDefault
Rulesets Analyze, CE, CI-checks
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Slow (1 hour)
Precision High
Examples Piwigo

1.2.155. Redefined Methods

Redefined methods are overwritten methods. Those methods are defined in different classes that are part of the same classes hierarchy.

Protected and public redefined methods replace each other. Private methods are kept separated, and depends on the caller to be distinguished.

<?php

class foo {
    function method() {
        return 1;
    }
}

class bar extends foo {
    function method() {
        return 2;
    }
}
?>

See also Object Inheritance.

1.2.155.1. Specs

Short name Classes/RedefinedMethods
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.156. Redefined Private Property

Private properties are local to their defined class. PHP doesn’t forbid the re-declaration of a private property in a child class.

However, having two or more properties with the same name, in the class hierarchy tends to be error prone.

<?php

class A {
    private $isReady = true;
}

class B {
    private $isReady = false;
}

?>

1.2.156.1. Specs

Short name Classes/RedefinedPrivateProperty
Rulesets Analyze
Exakt since 1.2.3
Php Version All
Severity Major
Time To Fix Slow (1 hour)
Precision High
Examples Zurmo

1.2.157. Redefined Property

Property redefined in a parent class.

Using heritage, it is possible to define several times the same property, at different levels of the hierarchy.

<?php

class foo {
    protected $aProperty = 1;
}

class bar extends foo {
    // This property is redefined in the parent class, leading to potential confusion
    protected $aProperty = 1;
}

?>

When this is the case, it is difficult to understand which class will actually handle the property.

In the case of a private property, the different instances will stay distinct. In the case of protected or public properties, they will all share the same value.

It is recommended to avoid redefining the same property in a hierarchy.

1.2.157.1. Specs

Short name Classes/RedefinedProperty
Rulesets ClassReview
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.158. Not Same Name As File

The class, interface or trait in this file as a different name, case included, than the file name.

In the following example, the file name is Foo.php. .. code-block:: php

<?php

// normal host of this file class Foo {

// some code

}

// case-typo this file class foo {

// some code

}

// strangely stored class class foo {

// some code

}

// This is valid name, but there is also a Foo class, and other classe in this file. interface Foo {}

?>

1.2.158.1. Specs

Short name Classes/SameNameAsFile
Rulesets none
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.159. Scalar Or Object Property

Property shouldn’t use both object and scalar syntaxes. When a property may be an object, it is recommended to implement the Null Object pattern : instead of checking if the property is scalar, make it always object.
<?php

class x {
    public $display = 'echo';

    function foo($string) {
        if (is_string($this->display)) {
            echo $this->string;
        } elseif ($this->display instanceof myDisplayInterface) {
            $display->display();
        } else {
            print Error when displaying\n;
        }
    }
}

interface myDisplayInterface {
    public function display($string); // does the display in its own way
}

class nullDisplay implements myDisplayInterface {
    // implements myDisplayInterface but does nothing
    public function display($string) {}
}

class x2 {
    public $display = null;

    public function __construct() {
        $this->display = new nullDisplay();
    }

    function foo($string) {
        // Keep the check, as $display is public, and may get wrong values
        if ($this->display instanceof myDisplayInterface) {
            $display->display();
        } else {
            print Error when displaying\n;
        }
    }
}

// Simple class for echo
class echoDisplay implements myDisplayInterface {
    // implements myDisplayInterface but does nothing
    public function display($string) {
        echo $string;
    }
}

?>

See also Null Object Pattern. and The Null Object Pattern.

1.2.159.1. Suggestions

  • Only use one type of syntax with your properties.

1.2.159.2. Specs

Short name Classes/ScalarOrObjectProperty
Rulesets Analyze
Exakt since 0.12.3
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High
Examples SugarCrm

1.2.160. Should Deep Clone

By default, PHP makes a shallow clone. It only clone the scalars, and keep the reference to any object already referenced. This means that the cloned object and its original share any object they hold as property.

This is where the magic method __clone() comes into play. It is called, when defined, at clone time, so that the cloned object may clone all the needed sub-objects.

It is recommended to use the __clone() method whenever the objects hold objects.

<?php

class a {
    public $b = null;

    function __construct() {
        $this->b =  new Stdclass();
        $this->b->c = 1;
    }
}

class ab extends a {
    function __clone() {
        $this->b = clone $this->b;
    }
}

// class A is shallow clone, so $a->b is not cloned
$a = new a();
$b = clone $a;
$a->b->c = 3;
echo $b->b->c;
// displays 3

// class Ab is deep clone, so $a->b is cloned
$a = new ab();
$b = clone $a;
$a->b->c = 3;
echo $b->b->c;
// displays 1

?>

See also PHP Clone and Shallow vs Deep Copying and Cloning objects.

1.2.160.1. Suggestions

1.2.160.2. Specs

Short name Classes/ShouldDeepClone
Rulesets Suggestions
Exakt since 1.7.0
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.161. Should Have Destructor

PHP destructors are called when the object has to be destroyed. By default, PHP calls recursively the destructor on internal objects, until everything is unset.

Unsetting objects and resources explicitly in the destructor is a good practice to reduce the amount of memory in use. It helps PHP resource counter to keep the numbers low, and easier to clean. This is a major advantage for long running scripts.

<?php

class x {
    function __construct() {
        $this->p = new y();
    }

    function __destruct() {
        print __METHOD__.PHP_EOL;
        unset($this->p);
    }
}

class y {
    function __construct() {
        print __METHOD__.PHP_EOL;
        $this->p = new y();
    }

    function __destruct() {
        print __METHOD__.PHP_EOL;
        unset($this->p);
    }
}

$a = (new x);
sleep(1);

// This increment the resource counter by one for the property.
$p = $a->p;
unset($a);
sleep(3);

print 'end'.PHP_EOL;
// Y destructor is only called here, as the object still exists in $p.

?>

See also Destructor, and Php Destructors.

1.2.161.1. Suggestions

  • Add a destruct method to the class to help clean at destruction time.

1.2.161.2. Specs

Short name Classes/ShouldHaveDestructor
Rulesets Suggestions
Exakt since 1.5.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.162. Could Use self

self keyword refers to the current class, or any of its parents. Using it is just as fast as the full class name, it is as readable and it is will not be changed upon class or namespace change.

It is also routinely used in traits : there, self represents the class in which the trait is used, or the trait itself.

<?php

class x {
    const FOO = 1;

    public function bar() {
        return self::FOO;
// same as return x::FOO;
    }
}

?>

See also Scope Resolution Operator (::).

1.2.162.1. Suggestions

  • replace the explicit name with self

1.2.162.2. Specs

Short name Classes/ShouldUseSelf
Rulesets Analyze, ClassReview, Suggestions
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Instant (5 mins)
Precision High
Examples WordPress, LiveZilla

1.2.163. Should Use Local Class

Methods should use the defining class, or be functions.

Methods should use $this with another method or a property, or call parent\:\:. Static methods should call another static method, or a static property. Methods which are overwritten by a child class are omitted : the parent class act as a default value for the children class, and this is correct.

<?php

class foo {
    public function __construct() {
        // This method should do something locally, or be removed.
    }
}

class bar extends foo {
    private $a = 1;

    public function __construct() {
        // Calling parent:: is sufficient
        parent::__construct();
    }

    public function barbar() {
        // This is acting on the local object
        $this->a++;
    }

    public function barfoo($b) {
        // This has no action on the local object. It could be a function or a closure where needed
        return 3 + $b;
    }
}

?>

Note that a method using a class constant is not considered as using the local class, for this analyzer.

1.2.163.1. Suggestions

  • Make this method a function
  • Actually use $this, or any related attributes of the class

1.2.163.2. Specs

Short name Classes/ShouldUseThis
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High
ClearPHP not-a-method

1.2.164. Static Methods Can’t Contain $this

Static methods are also called class methods : they may be called even if the class has no instantiated object. Thus, the local variable $this won’t exist, PHP will set it to NULL as usual.
<?php

class foo {
    // Static method may access other static methods, or property, or none.
    static function staticBar() {
        // This is not possible in a static method
        return self::otherStaticBar() . static::$staticProperty;
    }

    static function bar() {
        // This is not possible in a static method
        return $this->property;
    }
}

?>

Either this is not a static method, which is fixed by removing the static keyword, or replace all $this mention by static properties Class\:\:$property.

See also Static Keyword <https://www.php.net/manual/en/language.oop5.`static.php>`_

1.2.164.1. Suggestions

  • Remove any $this usage
  • Turn any $this usage into a static call : $this->foo() => self::foo()

1.2.164.2. Specs

Short name Classes/StaticContainsThis
Rulesets Analyze, CE, CI-checks
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High
ClearPHP no-static-this
Examples xataface, SugarCrm

1.2.165. Static Methods

List of all static methods.
<?php

class foo {
    static public function staticMethod() {

    }

    public function notStaticMethod() {

    }

    private function method() {
        // This is not a property
        new static();
    }
}

?>

1.2.165.1. Specs

Short name Classes/StaticMethods
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.166. Static Methods Called From Object

Static methods may be called without instantiating an object. As such, they never interact with the special variable ‘$this’, as they do not depend on object existence.

Besides this, static methods are normal methods that may be called directly from object context, to perform some utility task.

To maintain code readability, it is recommended to call static method in a static way, rather than within object context.

<?php
    class x {
        static function y( ) {}
    }

    $z = new x( );

    $z->y( ); // Readability : no one knows it is a static call
    x::y( );  // Readability : here we know
?>

1.2.166.1. Suggestions

  • Switch to static method syntax
  • Remove the static option from the method

1.2.166.2. Specs

Short name Classes/StaticMethodsCalledFromObject
Rulesets Analyze, CE, CI-checks
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.167. Static Properties

List of all static properties.
<?php

class foo {
    static public $staticProperty = 1;
           public $notStaticProperty = 2;

    private function method() {
        // This is not a property
        new static();
    }
}

function bar() {
    // This is not a static property
    static $staticVariable;

    //....
}

?>

1.2.167.1. Specs

Short name Classes/StaticProperties
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.168. Strange Names For Methods

Those methods should have another name.

Ever wondered why the __constructor is never called? Or the __consturct ?

Those errors most often originate from typos, or quick fixes that where not fully tested. Other times, they were badly chosen, or ran into PHP’s own reserved keywords.

<?php

class foo {
    // The real constructor
    function __construct() {}

    // The fake constructor
    function __constructor() {}

    // The 'typo'ed' constructor
    function __consturct() {}

    // This doesn't clone
    function clone() {}
}

?>

1.2.168.1. Suggestions

  • Use the proper name
  • Remove the method, when it is not used and tests still pass.

1.2.168.2. Specs

Short name Classes/StrangeName
Rulesets none
Exakt since 0.10.1
Php Version All
Severity Major
Time To Fix Slow (1 hour)
Precision High

1.2.169. Swapped Arguments

Overwritten methods must be compatible, but argument names is not part of that compatibility.

Methods with the same name, in two classes of the same hierarchy, must be compatible for typehint, default value, reference. The name of the argument is not taken into account when checking such compatibility, at least until PHP 7.4.

<?php

class x {
    function foo($a, $b) {}

    function bar($a, $b) {}
}

class y extends x {
    // foo is compatible (identical) with the above class
    function foo($a, $b) {}

    // bar is compatible with the above class, yet, the argument might not receive what they expect.
    function bar($b, $a) {}
}

?>

This analysis reports argument lists that differs in ordering. This analysis doesn’t report argument lists that also differs in argument names.

1.2.169.1. Suggestions

  • Make sure the names of the argument are in the same order in all classes and interfaces

1.2.169.2. Specs

Short name Classes/SwappedArguments
Rulesets Analyze
Exakt since 2.1.5
Php Version All
Severity Critical
Time To Fix Quick (30 mins)
Precision High

1.2.170. Test Class

Those are test classes, based on popular UT frameworks.

1.2.170.1. Specs

Short name Classes/TestClass
Rulesets CE
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.171. $this Belongs To Classes Or Traits

$this variable represents the current object, inside a class or trait scope.

It is a pseudo-variable, and should be used within class’s or trait’s methods and not outside. It should also not be used in static methods.

PHP 7.1 is stricter and check for $this at several situations. Some are found by static analysis, some are dynamic analysis.

<?php

// as an argument
function foo($this) {
    // Using global
    global $this;
    // Using static (not a property)
    static $this;

    // Can't unset it
    unset($this);

    try {
        // inside a foreach
        foreach($a as $this) {  }
        foreach($a as $this => $b) {  }
        foreach($a as $b => $this) {  }
    } catch (Exception $this) {
        // inside a catch
    }

    // with Variable Variable
    $a = this;
    $$a = 42;
}

class foo {
    function bar() {
        // Using references
        $a =& $this;
        $a = 42;

        // Using extract(), parse_str() or similar functions
        extract([this => 42]);  // throw new Error(Cannot re-assign $this)
        var_dump($this);
    }

    static function __call($name, $args) {
        // Using __call
        var_dump($this); // prints object(C)#1 (0) {}, php-7.0 printed NULL
        $this->test();   // prints ops
    }

}
?>

1.2.171.1. Suggestions

  • Do not use $this as a variable name, except for the current object, in a class, trait or closure.

1.2.171.2. Specs

Short name Classes/ThisIsForClasses
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High
Examples OpenEMR

1.2.172. $this Is Not An Array

$this variable represents the current object and it is not an array.

This is unless the class (or its parents) has the ArrayAccess interface, or extends ArrayObject or SimpleXMLElement.

<?php

// $this is an array
class Foo extends ArrayAccess {
    function bar() {
        ++$this[3];
    }
}

// $this is not an array
class Foo2 {
    function bar() {
        ++$this[3];
    }
}

?>

See also ArrayAccess, ArrayObject and The Basics.

1.2.172.1. Suggestions

  • Extends ArrayObject, or a class that extends it, to use $this as an array too.
  • Implements ArrayAccess to use $this as an array too.
  • Use a property in the current class to store the data, instead of $this directly.

1.2.172.2. Specs

Short name Classes/ThisIsNotAnArray
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High

1.2.173. $this Is Not For Static Methods

Static methods shouldn’t use $this variable.

$this variable represents an object, the current object. It is not compatible with a static method, which may operate without any object.

While executing a static method, $this is actually set to NULL.

<?php

class foo {
    static $staticProperty = 1;

    // Static methods should use static properties
    static public function count() {
        return self::$staticProperty++;
    }

    // Static methods can't use $this
    static public function bar() {
        return $this->a;   // No $this usage in a static method
    }
}

?>

See also Static Keyword <https://www.php.net/manual/en/language.oop5.`static.php>`_.

1.2.173.1. Suggestions

  • Remove the static keyword on the method, and update all calls to this method to use $this
  • Remove the usage of $this in the method, replacing it with static properties
  • Make $this an argument (and change its name) : then, make the method a function

1.2.173.2. Specs

Short name Classes/ThisIsNotForStatic
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High
ClearPHP no-static-this

1.2.174. Throw In Destruct

According to the manual, Attempting to throw an exception from a destructor (called in the time of script termination) causes a fatal error.

The destructor may be called during the lifespan of the script, but it is not certain. If the exception is thrown later, the script may end up with a fatal error.

Thus, it is recommended to avoid throwing exceptions within the __destruct method of a class.

<?php

// No exception thrown
class Bar {
    function __construct() {
        throw new Exception('__construct');
    }

    function __destruct() {
        $this->cleanObject();
    }
}

// Potential crash
class Foo {
    function __destruct() {
        throw new Exception('__destruct');
    }
}

?>

See also Constructors and Destructors.

1.2.174.1. Suggestions

  • Remove any exception thrown from a destructor

1.2.174.2. Specs

Short name Classes/ThrowInDestruct
Rulesets Analyze, CE, CI-checks
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High

1.2.175. Too Many Children

Classes that have more than 15 children. It is worth checking if they cannot be refactored in anyway.

The threshold of 15 children can be configured. There is no technical limitation of the number of children and grand-children for a class.

The analysis doesn’t work recursively : only direct generations are counted. Only children that can be found in the code are counted.

<?php

// parent class
// calling it grandparent to avoid confusion with 'parent'
class grandparent {}


class children1 extends grandparent {}
class children2 extends grandparent {}
class children3 extends grandparent {}
class children4 extends grandparent {}
class children5 extends grandparent {}
class children6 extends grandparent {}
class children7 extends grandparent {}
class children8 extends grandparent {}
class children9 extends grandparent {}
class children11 extends grandparent {}
class children12 extends grandparent {}
class children13 extends grandparent {}
class children14 extends grandparent {}
class children15 extends grandparent {}
class children16 extends grandparent {}
class children17 extends grandparent {}
class children18 extends grandparent {}
class children19 extends grandparent {}

?>

See also Why is subclassing too much bad (and hence why should we use prototypes to do away with it)?.

1.2.175.1. Suggestions

  • Split the original class into more specialised classes
Name Default Type Description
childrenClassCount 15 integer Threshold for too many children classes for one class.

1.2.175.2. Specs

Short name Classes/TooManyChildren
Rulesets Suggestions
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High
Examples Typo3, Woocommerce

1.2.176. Too Many Dereferencing

Linking too many properties and methods, one to the other.

This analysis counts both static calls and normal call; methods, properties and constants. It also takes into account arrays along the way.

The default limit of chaining methods and properties is set to 7 by default.

<?php

// 9 chained calls.
$main->getA()->getB()->getC()->getD()->getE()->getF()->getG()->getH()->getI()->property;

?>

Too many chained methods is harder to read.

1.2.176.1. Suggestions

Name Default Type Description
tooManyDereferencing 7 integer Maximum number of dereferencing.

1.2.176.2. Specs

Short name Classes/TooManyDereferencing
Rulesets Analyze
Exakt since 1.9.7
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.177. Too Many Finds

Too many methods called ‘find*’ in this class. It is may be time to consider the Specification pattern.
<?php

// quite a fishy interface
interface UserInterface {
    public function findByEmail($email);
    public function findByUsername($username);
    public function findByFirstName($firstname);
    public function findByLastName($lastname);
    public function findByName($name);
    public function findById($id);

    public function insert($user);
    public function update($user);
}

?>

See also On Taming Repository Classes in Doctrine , On Taming Repository Classes in Doctrine… Among other things., specifications.

Name Default Type Description
minimumFinds 5 integer Minimal number of prefixed methods to report.
findPrefix find string list of prefix to use when detecting the ‘find’. Comma-separated list, case insensitive.
findSuffix   string list of fix to use when detecting the ‘find’. Comma-separated list, case insensitive.

1.2.177.1. Specs

Short name Classes/TooManyFinds
Rulesets Analyze
Exakt since 0.10.5
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.178. Too Many Injections

When a class is constructed with more than four dependencies, it should be split into smaller classes.
<?php

// This class relies on 5 other instances.
// It is probably doing too much.
class Foo {
    public function __construct(
            A $a,
            B $b,
            C $c,
            D $d
            E $e ) {
        $this->a = $a;
        $this->b = $b;
        $this->d = $d;
        $this->d = $d;
        $this->e = $e;
    }
}

?>

See also Dependency Injection Smells.

1.2.178.1. Suggestions

  • Split the class into smaller classes. Try to do less in that class.
Name Default Type Description
injectionsCount 5 integer Threshold for too many injected parameters for one class.

1.2.178.2. Specs

Short name Classes/TooManyInjections
Rulesets Analyze
Exakt since 0.11.6
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High
Examples NextCloud, Thelia

1.2.179. Magic Visibility

The class magic methods must have public visibility and cannot be static.
<?php

class foo{
    // magic method must bt public and non-static
    public static function __clone($name) {    }

    // magic method can't be private
    private function __get($name) {    }

    // magic method can't be protected
    private function __set($name, $value) {    }

    // magic method can't be static
    public static function __isset($name) {    }
}

?>

See also Magic methods.

1.2.179.1. Specs

Short name Classes/toStringPss
Rulesets CompatibilityPHP70
Exakt since 0.8.4
Php Version 5.4-
Severity Major
Time To Fix Quick (30 mins)
Precision High

1.2.180. DI Cyclic Dependencies

When injecting dependencies, classes that mutually depend on each other is a code smell.

Dependency injection should be organized as an acyclic tree-like structure

<?php

// Classes A and B depends on each other.
class A {
    protected $b;

    public function __construct(B $b) {
        $this->b = $b;
    }
}

class B {
    public $a;

    protected function setA(A $a) {
        $this->a = $a;
    }
}
?>

See also Dependency Injection Smells.

1.2.180.1. Specs

Short name Classes/TypehintCyclicDependencies
Rulesets none
Exakt since 0.11.6
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.181. Wrong Access Style to Property

Use the right syntax when reaching for a property. Static properties use the \:\: operator, and non-static properties use ->.

Mistaking one of the other raise two different reactions from PHP : Access to undeclared `static <https://www.php.net/manual/en/language.oop5.static.php>`_ property is a fatal error, while PHP Notice:  Accessing `static <https://www.php.net/manual/en/language.oop5.static.php>`_ property aa\:\:$a as non `static <https://www.php.net/manual/en/language.oop5.static.php>`_ is a notice.

<?php

class a {
    static public $a = 1;

    function foo() {
        echo self::$a; // right
        echo $this->a; // WRONG
    }
}

class b {
    public $b = 1;

    function foo() {
        echo $this->$b;  // right
        echo b::$b;      // WRONG
    }
}

?>

This analysis reports both static properties with a -> access, and non-static properties with a :: access.

See also Static Keyword <https://www.php.net/manual/en/language.oop5.`static.php>`_.

1.2.181.1. Suggestions

  • Match the property call with the definition
  • Make the property static

1.2.181.2. Specs

Short name Classes/UndeclaredStaticProperty
Rulesets Analyze, CE, CI-checks, ClassReview
Exakt since 1.4.9
Php Version All
Severity Critical
Time To Fix Quick (30 mins)
Precision High
Examples HuMo-Gen

1.2.182. Undefined Classes

Those classes are used in the code, but there are no definition for them.

This may happens under normal conditions, if the application makes use of an unsupported extension, that defines extra classes; or if some external libraries, such as PEAR, are not provided during the analysis.

<?php

// FPDF is a classic PDF class, that is usually omitted by Exakat.
$o = new FPDF();

// Exakat reports undefined classes in instanceof
// PHP ignores them
if ($o instanceof SomeClass) {
    // doSomething();
}

// Classes may be used in typehint too
function foo(TypeHintClass $x) {
    // doSomething();
}

?>

This analysis also checks in attributes.

1.2.182.1. Suggestions

  • Fix the typo in the class name
  • Add a missing ‘use’ expression
  • Create the missing class

1.2.182.2. Specs

Short name Classes/UndefinedClasses
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Slow (1 hour)
Precision Medium

1.2.183. Undefined Class Constants

Class constants that are used, but never defined. This should yield a fatal error upon execution, but no feedback at compile level.
<?php

class foo {
    const A = 1;
    define('B', 2);
}

// here, C is not defined in the code and is reported
echo foo::A.foo::B.foo::C;

?>

1.2.183.1. Suggestions

  • Fix the name of the constant
  • Add the constant to the current class or one of its parent
  • Update the constant’s visibility

1.2.183.2. Specs

Short name Classes/UndefinedConstants
Rulesets Analyze, CE, CI-checks
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High

1.2.184. Undefined Parent

List of properties and methods that are accessed using parent keyword but are not defined in the parent classes.

This may compile but, eventually yields a fatal error during execution.

<?php

class theParent {
    // No bar() method
    // private bar() method is not accessible to theChild
}

class theChild extends theParent {
    function foo() {
        // bar is defined in theChild, but not theParent
        parent::bar();
    }

    function bar() {

    }
}

?>

Note that if the parent is defined using extends someClass but someClass is not available in the tested code, it will not be reported : it may be in composer, another dependency, or just missing.

See also parent <https://www.php.net/manual/en/keyword.`parent.php>`_.

1.2.184.1. Suggestions

  • Remove the usage of the found method
  • Add a definition for the method in the appropriate parent
  • Fix the name of the method, and replace it with a valid definition
  • Change ‘parent’ with ‘self’ if the method is eventually defined in the current class
  • Change ‘parent’ with another object, if the method has been defined in another class
  • Add the ‘extends’ keyword to the class, to actually have a parent class

1.2.184.2. Specs

Short name Classes/UndefinedParentMP
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.185. Undefined Properties

List of properties that are not explicitly defined in the class, its parents or traits.
<?php

class foo {
    // property definition
    private bar = 2;

    function foofoo() {
        // $this->bar is defined in the class
        // $this->barbar is NOT defined in the class
        return $this->bar + $this->barbar;
    }
}

?>

It is possible to spot unidentified properties by using the PHP’s magic methods __get and __set. Even if the class doesn’t use magic methods, any call to an undefined property will be directed to those methods, and they can be used as a canary, warning that the code is missing a definition.

<?php

trait NoUnefinedProperties {
     function __get($name) {
             assert(false, "Attempt to read the $name property, on the class ".__CLASS__;
     }

     function __set($name, $value) {
             assert(false, "Attempt to read the $name property, on the class ".__CLASS__;
     }
}

?>

See also Properties.

1.2.185.1. Suggestions

  • Add an explicit property definition, and give it null as a default value : this way, it behaves the same as undefined.
  • Rename the property to one that exists already.

1.2.185.2. Specs

Short name Classes/UndefinedProperty
Rulesets Analyze, CE, CI-checks
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High
ClearPHP no-undefined-properties
Examples WordPress, MediaWiki

1.2.186. Undefined ::class

\:\:class doesn’t check if a corresponding class exists.

\:\:class must be checked with a call to class_exists(). Otherwise, it may lead to a Class 'foo' not found or even silent dead code : this happens also with Catch and instanceof commands with undefined classes. PHP doesn’t raise an error in that case.

<?php

class foo() {}

// prints foo
echo foo::class;

// prints bar though bar doesn't exist.
echo bar::class;

?>

See also Class Constants.

1.2.186.1. Specs

Short name Classes/UndefinedStaticclass
Rulesets Analyze, CE, CI-checks
Exakt since 1.3.5
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High

1.2.187. Undefined static:: Or self::

self and static refer to the current class, or one of its parent. The property or the method may be undefined.
<?php

class x {
    static public function definedStatic() {}
    private definedStatic = 1;

    public function method() {
        self::definedStatic();
        self::undefinedStatic();

        static::definedStatic;
        static::undefinedStatic;
    }
}

?>

See also Late `Static Bindings <https://www.php.net/manual/en/language.oop5.late-static-bindings.php>`_.

1.2.187.1. Suggestions

  • Define the missing method or property
  • Remove usage of that undefined method or property
  • Fix name to call an actual local structure

1.2.187.2. Specs

Short name Classes/UndefinedStaticMP
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High
Examples xataface, SugarCrm

1.2.188. Uninitialized Property

Uninitilized properties are not fully bootstrapped at the end of the constructor.

Properties may be inited at definition time, along with their visibility and type. Some types are not inited at definition time, as any object, so they should be inited during constructor. At the end of the former, all properties shall have a legit value, and be ready for usage.

<?php

class x {
    private $foo = null;
    private $uninited;

    function __construct($arg) {
        $this->foo = $args;

        // $this->uninited is not inited, nor at definition, nor in constructor
        // it will hold null at the beginning of the next method call
    }
}

?>

1.2.188.1. Suggestions

  • Remove the property, and move it to another class
  • Add an initialisation for this property

1.2.188.2. Specs

Short name Classes/UninitedProperty
Rulesets ClassReview
Exakt since 2.0.9
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision Medium

1.2.189. Unitialized Properties

Properties that are not initialized in the constructor, nor at definition.
<?php

class X {
    private $i1 = 1, $i2;
    protected $u1, $u2;

    function __construct() {
        $this->i2 = 1 + $this->u2;
    }

    function m() {
        echo $this->i1, $this->i2, $this->u1, $this->u2;
    }
}
?>

With the above class, when m() is accessed right after instantiation, there will be a missing property. Using default values at property definition, or setting default values in the constructor ensures that the created object is consistent.

1.2.189.1. Suggestions

  • Add an explicit initialization for each property.

1.2.189.2. Specs

Short name Classes/UnitializedProperties
Rulesets Suggestions, Top10
Exakt since 0.8.9
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High
Examples SPIP

1.2.190. Unreachable Class Constant

Class constants may be unreachable due to visibility configuration.

Since PHP 7.1, class constants support visibility. Their usage may be restricted to the current class, or private, to classes that extends or are extended by the current class, or protected. They may also be public, just like it was before.

<?php

class Foo{
    private const PRIVATE = 1;
            const PUBLIC = 3;
}

// PHP 7.1- and older
echo Foo::PUBLIC;

// This is not accessible
echo Foo::PRIVATE;

?>

See also Class Constant and PHP RFC: Support Class Constant Visibility.

1.2.190.1. Suggestions

  • Make the class constant protected, when the call to the constant is inside a related class.
  • Create another constant, that may be accessible
  • Make the class constant public

1.2.190.2. Specs

Short name Classes/UnreachableConstant
Rulesets ClassReview
Exakt since 1.5.4
Php Version All
Severity Major
Time To Fix Slow (1 hour)
Precision High

1.2.191. Unresolved Catch

Catch clauses do not check for Exception existence.

Catch clauses check that the emitted expression is of the requested Class, but if that class doesn’t exist in the code, the catch clause is always false. This is dead code.

<?php

try {
    // doSomething()
} catch {TypoedExxeption $e) { // Do not exist Exception
    // Fix this exception
} catch {Stdclass $e) {        // Exists, but is not an exception
    // Fix this exception
} catch {Exception $e) {        // Actual and effective catch
    // Fix this exception
}
?>

1.2.191.1. Suggestions

  • Fix the name of the exception
  • Remove the catch clause
  • Add a use expression with a valid name
  • Create/import the missing exception

1.2.191.2. Specs

Short name Classes/UnresolvedCatch
Rulesets Dead code
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High
ClearPHP no-unresolved-catch

1.2.192. Unresolved Classes

The following classes are instantiated in the code, but their definition couldn’t be found.
<?php

class Foo extends Bar {
    private function foobar() {
        // here, parent is not resolved, as Bar is not defined in the code.
        return parent::$prop;
    }
}

?>

1.2.192.1. Suggestions

  • Check for namespaces and aliases and make sure they are correctly configured.

1.2.192.2. Specs

Short name Classes/UnresolvedClasses
Rulesets Analyze
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High

1.2.193. Unresolved Instanceof

The instanceof operator doesn’t confirm if the compared class exists.

It checks if an variable is of a specific class. However, if the referenced class doesn’t exist, because of a bug, a missed inclusion or a typo, the operator always fails, without a warning.

<?php

namespace X {
    class C {}

    // This is OK, as C is defined in X
    if ($o instanceof C) { }

    // This is not OK, as C is not defined in global
    // instanceof respects namespaces and use expressions
    if ($o instanceof \C) { }

    // This is not OK, as undefinedClass
    if ($o instanceof undefinedClass) { }

    // This is not OK, as $class is now a full namespace. It actually refers to \c, which doesn't exist
    $class = 'C';
    if ($o instanceof $class) { }
}
?>

Make sure the following classes are well defined.

See also Instanceof.

1.2.193.1. Suggestions

  • Remove the call to instanceof and all its dependencies.
  • Fix the class name and use a class existing in the project.

1.2.193.2. Specs

Short name Classes/UnresolvedInstanceof
Rulesets Analyze, Dead code, Top10
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Instant (5 mins)
Precision High
ClearPHP no-unresolved-instanceof
Examples WordPress

1.2.194. Unused Classes

The following classes are never explicitly used in the code.

Note that this may be valid in case the current code is a library or framework, since it defines classes that are used by other (unprovided) codes. Also, this analyzer may find classes that are, in fact, dynamically loaded.

<?php

class unusedClasss {}
class usedClass {}

$y = new usedClass();

?>

1.2.194.1. Suggestions

  • Remove unused classes
  • Make use of unused classes
  • Fix class name

1.2.194.2. Specs

Short name Classes/UnusedClass
Rulesets Analyze, Dead code
Exakt since 0.8.4
Php Version All
Severity Major
Time To Fix Quick (30 mins)
Precision High

1.2.195. Unused Class Constant

The class constant is unused. Consider removing it.
<?php

class foo {
    public const UNUSED = 1; // No mention in the code

    private const USED = 2;  // used constant

    function bar() {
        echo self::USED;
    }
}

?>

1.2.195.1. Suggestions

  • Remove the class constant
  • Use the class constant

1.2.195.2. Specs

Short name Classes/UnusedConstant
Rulesets Analyze, ClassReview
Exakt since 1.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.196. Unused Methods

Those methods are never called.

They are probably dead code, unless they are called dynamically.

This analysis omits methods which are in a class that makes dynamical self calls : $this->$m(). That way, any method may be called.

This analysis omits methods which are overwritten by a child class. That way, they are considered to provide a default behavior.

<?php

class foo {
    public function used() {
        $this->used();
    }

    public function unused() {
        $this->used();
    }
}

class bar extends foo {
    public function some() {
        $this->used();
    }
}

$a = new foo();
$a->used();

?>

See also Dead Code: Unused Method.

1.2.196.1. Suggestions

  • Make use of the method
  • Remove the method
  • Move the method to another class

1.2.196.2. Specs

Short name Classes/UnusedMethods
Rulesets Dead code
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Slow (1 hour)
Precision High

1.2.197. Unused Private Methods

Private methods that are not used are dead code.

Private methods are reserved for the defining class. Thus, they must be used with the current class, with $this or self\:\:.

Protected methods, in a standalone class, are also included.

<?php

class Foo {
    // Those methods are used
    private function method() {}
    private static function staticMethod() {}

    // Those methods are not used
    private function unusedMethod() {}
    private static function staticUnusedMethod() {}

    public function bar() {
        self::staticMethod();
        $this->method();
    }
}

?>

This analysis skips classes that makes self dynamic calls, such as $this->$method().

1.2.197.1. Suggestions

  • Remove the private method, as it is unused
  • Add a call to this private method
  • Change method visibility to make it available to other classes

1.2.197.2. Specs

Short name Classes/UnusedPrivateMethod
Rulesets Dead code
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High

1.2.198. Unused Private Properties

Unused static properties should be removed.

Unused private properties are dead code. They are usually leftovers of development or refactorisation : they used to have a mission, but are now left.

Being private, those properties are only accessible to the current class or trait. As such, validating the

<?php

class foo {
    // This is a used property (see bar method)
    private $used = 1;

    // This is an unused property
    private $unused = 2;

    function bar($a) {
        $this->used += $a;

        return $this->used;
    }
}

?>

1.2.198.1. Suggestions

  • Remove the property altogether
  • Check if the property wasn’t forgotten in the rest of the class
  • Check if the property is correctly named
  • Change the visibility to protected or public : may be a visibility refactoring was too harsh

1.2.198.2. Specs

Short name Classes/UnusedPrivateProperty
Rulesets Dead code
Exakt since 0.8.4
Php Version All
Severity Minor
Time To Fix Quick (30 mins)
Precision High
Examples OpenEMR, phpadsnew

1.2.199. Unused Protected Methods

The following protected methods are unused in children class. As such, they may be considered for being private.

Methods reported by this analysis are not used by children, yet they are protected.

<?php

class Foo {
    // This method is not used
    protected function unusedBar() {}