Skip to content

Inspections

David Rodrigues edited this page Aug 14, 2024 · 35 revisions

Currently, 56 inspections have been implemented.

Code style

Anonymous function can be static

This inspection checks whether an anonymous function can be static.

Using static functions can improve resource consumption, but it is considered a micro-optimization. Therefore, the focus here is purely on code style.

Array can be packed

This inspection highlights that some array structures can be simplified.

Example: [ 0 => 'a', 1 => 'b' ] can be replaced with [ 'a', 'b' ].

Call to __toString() can be simplified

This inspection suggests replacing __toString() with a simple type cast (string).

Case separator format

This inspection reinforces the type of separator used after the switch() case/default clauses, which can be a colon (e.g., case 123: ...) or semicolon (e.g., case 123; ...).

Class name as string can be replaced

This inspection identifies class names being specified as a string, and then suggests replacing them with the equivalent as ::class.

Class self-reference format normalization

This inspection normalizes the class self-reference format (e.g., ClassName::class becomes self::class, or vice versa).

Comparison order with scalar normalization

This inspection helps normalize the order of comparisons with scalar types such as strings, numbers, and constants in general.

You can decide whether you prefer scalar types to always be on the left or right side. In programming, keeping scalar types on the left side is known as Yoda style.

Function to spread

This inspection identifies functions that can be replaced by spread. This includes functions like array_merge().

Example:

$example = array_merge($a, $b);

Becomes:

$example = [ ...$a, ...$b ];

Null check format

This inspection helps normalize the format of the null check. You can choose to use the is_null() function or the === comparison.

Even though is_null() is a function, PHP has enough optimization that the cost is exactly the same as a comparison. So just pay attention to the code style. There are no gains or losses here beyond that.

Nullable type format

This inspection allows normalizing the definition of nullable types.

You can choose between using the short format (?int) or the long format (int|null).

Nullable type on the rightmost side

This inspection reinforces that the nullable type (null itself) should always be the rightmost type among the types.

Example: In a list of types like null|string|int, it will be suggested to use string|int|null.

Parameter defaults to null

This inspection enforces that function parameters that have a default value should never set a value other than null. The default value should be defined by the function itself when the argument is null.

This way, the user won't need to rewrite the function's default value when modifying the next parameter. Additionally, if the function is eventually modified, the user won't need to update it.

Example:

function clue($items, $between = ", ", $last = " and ") {
    return /** ... */;
}

// Note that it is necessary to rewrite the function's 2nd default argument.
echo clue([ "a", "b", "c" ], ", ", " or ");

Becomes:

function clue($items, $between = null, $last = null) {
    $between ??= ", ";
    $last    ??= " and ";

    return /** ... */;
}

// Now just use `null` and the function will decide the correct value.
echo clue([ "a", "b", "c" ], null, " or ")

Parameter is implicitly nullable

This inspection enforces that a typed parameter with a default value of null explicitly defines null as the type.

You can specify the format of the auto-fix as either short (?int) or long (int|null). Please note that the long format is only supported in PHP projects version 8.0 onwards, so the short format will be used for older PHP versions automatically.

Replace backtick operator

This inspection suggests replacing the backtick operator (`example`) with its equivalent function (shell_exec()).

This helps to reduce visual clutter when reading the code and makes the expected behavior more explicit.

Replace function cast to type cast

This inspection checks the use of function cast (e.g., intval(), strval(), etc.) and suggests replacing it with type cast (e.g., (int), (string), etc.).

Furthermore, this modification is considered a good micro-optimization.

Replace with compact()

This inspection checks for an opportunity to replace an array (whose keys represent variables of the same name) with compact().

You can choose the preferred format of the generated arguments:

  • **Positional arguments (as default):** generates as `` compact("a", "b", "c") ``
  • **Named arguments:** generates as `` compact(var_name: ["a", "b", "c"]) `` (for PHP 8.0+ only)

Sort use() variables

This inspection reinforces that the order of variables in the use() clause should be the same as the order in which they are used internally by the function.

String can be simplified

This inspection identifies strings that can be simplified by using a type cast (string).

Type cast normalization

This inspection helps normalize the format of type casts for int, float, and bool. You can choose to use the short or long format.

Additionally, it updates older type casts such as double and real to float.

Unary increase/decrease format

This inspection helps normalize the format of increment and decrement unary expressions ($a++ and $a--, respectively), allowing you to decide which side the operator should be present on.

However, not every unary expression can be modified, so this inspection only acts under safe conditions.

Variable must have curly braces

This inspection enforces the use of curly braces on variables within strings to clarify the intent of the code.

Code smell

Array unpacking can be simplified

This inspection identifies unnecessary unpacking of arrays and suggests replacing them with the array itself.

Duplicated terms in compact()

This inspection identifies duplicated terms in the compact() function.

Function call using error control operator

This inspection checks the use of the error control operator, also known as the at-operator (@), which allows you to suppress errors that may occur during the execution of a function.

However, its use is not recommended since important errors can be suppressed and modify the expected behavior of the application.

Only use this operator at specific points, such as to avoid a race condition using functions like mkdir().

Missing #[Override] attribute

This inspection helps you structure overridden methods more consistently by using the #[Override] attribute introduced in PHP 8.3.

Replace optional() function

This inspection identifies the use of the optional() function, implemented by frameworks like Laravel, and suggests replacing it with the PHP 8.0+ null safe operator, if available.

Example:

return optional($user->profile)->twitter_id;

Becomes:

return $user->profile?->twitter_id;

Replace with null-safe operator

This inspection finds the use of the && operator which can be simplified into the use of the null-safe operator, available since PHP 8. A (bool) cast can be applied under certain conditions to maintain the expected behavior.

Example:

return $date && $date->isTomorrow();

Becomes:

return $date?->isTomorrow();

Senseless array_merge() usage

This inspection checks for senseless usage of array_merge().

In short, you should use array_merge() only when you have a set of arrays greater than one.

Senseless call to empty parent method

This inspection identifies calls to empty methods belonging to the parent class.

Empty methods are usually created to indicate that an implementation of the class determines that an abstract method serves no purpose at that level and can be implemented at lower levels.

abstract class A {
    abstract function example();
}

class B extends A {
    function example() { /* literally nothing */ }
}

class C extends B {
    function example() {
        parent::example(); // why?
        /* doSomething() */
    }
}

Senseless number_format() with zero decimal point

This inspection checks for calls to the number_format() function using zero as the decimal argument. This means that the function used is unnecessary and can be replaced by type casting, resulting in a performance gain of 50%+.

Usage of alias function

This inspection helps avoid using alias functions by suggesting replacing them with the target function.

Useless comparison

This inspection identifies simple cases where a type-checking is used unnecessarily.

For example:

$x = 123;

if (is_int($x)) { ... }

In this case, it's easy to understand that is_int() will always be true since we can easily see that $x is an integer.

Code error

Class name must match the file that stores it

This inspection verifies that the case of the class name that defines the file is the same as the name of the file. This difference can cause problems when publishing the project to a Unix environment.

Illegal #[Override] attribute

This inspection finds where the #[Override] attribute is used incorrectly. This means that a method is marked as an override when it's not actually overriding another method. In such cases, it's required to remove the attribute to prevent fatal errors in PHP 8.3 and later.

Invalid compact() argument

This inspection identifies invalid arguments for the compact() function, which accepts only strings, arrays of strings, or variables representing these types.

Static anonymous function can't access $this

This inspection checks if a static anonymous function refers to $this, which results in a fatal error.

Usage of compact() inside short functions

Using the compact() function can cause a bug in PHP (#78970) where the expected variable cannot be imported automatically.

In this case, the suggestion is to avoid using this function inside short functions until this problem is resolved.

Using native types as objects

This inspection identifies the mistaken use of a variable related to a native type as if it were an object, which generates a fatal error.

Code warning

Dangerous extract() call

This inspection checks for a dangerous call to the extract() function. This function allows extracting an array where the keys represent the variable names to be extracted. If an extraction occurs without proper validation, a malicious actor could modify variables and alter the expected behavior of the application.

Consider the following code:

$isAdministrator = $user->isAdministrator(); // A true check.
extract(Request::post()); // You shouldn't be doing this...

In the above case, if Request::post() contains something like [ "isAdministrator" => true ], the previous variable will be overwritten with the value true.

To protect against this, you can use the second parameter EXTR_SKIP, which allows variables to be created only if they don't already exist. Alternatively, you can keep using explicitly EXTR_OVERWRITE, which is the default, but only when you are certain about what you're doing.

Debug function usage

This inspection notifies the use of debug functions, assisting in locating and removing them before the production step.

Missing parent::call()

This inspection ensures that an overridden method is calling its parent method, guaranteeing that the class will maintain the behavior declared by the parent method.

By default, this inspection will occur even if you have explicitly added the #[Override] attribute to the method, but you can disable this option. If you do so, methods with this attribute will not require calls to the method defined in the parent.

Obsolete function usage

This inspection suggests replacing deprecated functions with their respective safer versions.

Sensitive parameter usage

This inspection checks if potentially sensitive parameters are protected by the #[SensitiveParameter] attribute. Protecting parameters in this way ensures that in logs or debugging, sensitive information such as passwords or bank codes is replaced with a placeholder value.

This feature will be available in PHP 8.2+ projects.

You can include or exclude other names in the options, in addition to the default ones.

Strict comparison usage

This inspection indicates when the strict comparison === or !== can be safely used instead of the loose comparison == or !=, respectively.

In certain cases, when the compared values have the data type, using the strict comparison ensures a more accurate and reliable comparison.

Usage of backslash on filesystem-related names

This inspection identifies the use of backslashes (e.g., dir\file.php) in file system-related functions, including the include and require expressions.

Backslashes are only allowed in Windows. When running the file on a Unix server, for example, you are likely to encounter serious problems.

Variable usage in compact()

This inspection identifies the use of literal variables as an argument to the compact() function. This is usually an error, as this function should only take strings.

Deprecation

Dollar sign outside of the curly braces

This inspection checks the usage of the dollar sign ($) outside of the curly braces on strings, which is deprecated as of PHP 8.2.

Important: Using the dollar sign inside curly braces is still allowed (e.g., "{$x}"), but using it outside (e.g., "${x}") is no longer allowed.

The difference in usage is subtle, so this inspection can help you avoid this type of problem.

Flow optimization

Drop useless conditional

This inspection identifies conditionals that can be safely removed since their else structure is identical to the main structure.

First-class callable replacement for array_map()

This inspection checks calls to array_map() that can be converted to first-class callables.

Available as of PHP 8.1.

Merge simple nested conditionals

This inspection identifies nested if() conditions that can be merged into one. However, complex conditions are ignored to maintain better code readability.

Example:

if (condition()) {
    if (anotherCondition()) {
        return true;
    }
}

Becomes:

if (condition() && anotherCondition()) {
    return true;
}

Merge simple subsequent conditionals

This inspection identifies if() conditions that can be merged with subsequent ones. However, complex conditions are ignored to maintain better code readability.

Example:

if (condition()) {
    return true;
}

if (anotherCondition()) {
    return true;
}

Becomes:

if (condition() || anotherCondition()) {
    return true;
}

Redundant return point

This inspection identifies redundant return points that can be safely removed.

Example:

if ($conditional) {
    doSomething();

    // Note: this return point is unnecessary since after this if() statement,
    // the same return will happen.
    return true;
}

return true;

Return-ternary can be replaced by if()

This inspection aims to avoid the use of the return-ternary construct, suggesting its replacement with an if() statement. This makes reading and maintenance simpler.

Example:

return expr() ? 123 : 456;

Becomes:

if (expr()) {
    return 123;
}

return 456;

Simplify ternary operation

This inspection analyzes the possibility of simplifying ternary operators with identical or non-identical comparisons.

For example, the code $x === $y ? $y : $x can be simplified to just $x, since if the comparison is true, it means that the true side is the value being compared ($y). And since the false side returns the expression itself as well, then the ternary operator is unnecessary since the result will always be the expression itself.

Example:

return $x === 123 ? 123 : $x;

// If $x is 123, then return 123 (the value of $x itself);
// If $x is not 123, then return the value of $x itself;
// Therefore, the value of $x itself is always returned.

Dead code

Unused use() reference for variable

This inspection identifies the reference usage of variables in the use() clause that are never used in write mode. Therefore, the reference can be safely removed.

Example:

$example = function () use (&$a, $b) {
    return $a + $b;
}

Becomes:

$example = function () use ($a, $b) {
    return $a + $b;
}

Unused use() variable

This inspection identifies variables declared in the use() clause of anonymous functions that are not being used and can be safely removed.

Clone this wiki locally