carthage-software/mago
Mago is an extremely fast PHP linter, formatter, and static analyzer written in Rust. It brings Rust-inspired speed and reliability to PHP projects with a modern toolchain and great developer experience, plus multiple install options (script, Homebrew, Composer).
This document details the rules available in the Redundancy category.
| Rule | Code |
|---|---|
| Constant Condition | constant-condition |
| Inline Variable Return | inline-variable-return |
| No Closing Tag | no-closing-tag |
| No Empty Comment | no-empty-comment |
| No Empty Loop | no-empty-loop |
| No Is Null | no-is-null |
| No Iterator To Array In Foreach | no-iterator-to-array-in-foreach |
| No Noop | no-noop |
| No Protected in Final | no-protected-in-final |
| No Redundant Binary String Prefix | no-redundant-binary-string-prefix |
| No Redundant Block | no-redundant-block |
| No Redundant Continue | no-redundant-continue |
| No Redundant File | no-redundant-file |
| No Redundant Final | no-redundant-final |
| No Redundant Isset | no-redundant-isset |
| No Redundant Label | no-redundant-label |
| No Redundant Literal Return | no-redundant-literal-return |
| No Redundant Math | no-redundant-math |
| No Redundant Method Override | no-redundant-method-override |
| No Redundant Nullsafe | no-redundant-nullsafe |
| No Redundant Parentheses | no-redundant-parentheses |
| No Redundant Readonly | no-redundant-readonly |
| No Redundant String Concat | no-redundant-string-concat |
| No Redundant Use | no-redundant-use |
| No Redundant Write Visibility | no-redundant-write-visibility |
| No Redundant Yield From | no-redundant-yield-from |
| No Self Assignment | no-self-assignment |
constant-conditionDetects if statements where the condition is a constant that always
evaluates to true or false.
Such statements are redundant. If the condition is always true, the if
wrapper is unnecessary. If it's always false, the enclosed code is dead
and can be removed or refactored.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
if ($variable > 10) {
echo "Greater than 10";
}
<?php
if (true) {
echo "This will always run";
}
if (false) {
echo "This is dead code";
}
inline-variable-returnDetects unnecessary variable assignments immediately before returning the variable.
When a variable is only used once right after being assigned, the assignment can be inlined into the return statement.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"warning" |
<?php
function getValue() {
return computeResult();
}
function process() {
$result = computeResult();
log($result);
return $result;
}
<?php
function getValue() {
$result = computeResult();
return $result;
}
function getArray() {
$arr = [1, 2, 3];
return $arr;
}
no-closing-tagDetects redundant closing tags ( ?> ) at the end of a file.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
echo "Hello, world!";
<?php
echo "Hello, world!";
?>
no-empty-commentDetects empty comments in the codebase. Empty comments are not useful and should be removed to keep the codebase clean and maintainable.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"note" |
preserve-single-line-comments |
boolean |
false |
<?php
// This is a useful comment.
//
// And so is this whole single line comment block, including the enclosed empty line.
# This is also a useful comment.
/**
* This is a docblock.
*/
<?php
//
#
/**/
no-empty-loopDetects loops (for, foreach, while, do-while) that have an empty body. An empty
loop body does not perform any actions and is likely a mistake or redundant code.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"note" |
<?php
foreach ($items as $item) {
process($item);
}
<?php
while (should_wait()) {
// Empty loop body
}
no-is-nullDetects usage of the is_null() function and suggests using a strict === null comparison instead.
The is_null() function is redundant because === null achieves the same result with clearer intent
and without the overhead of a function call.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
false |
level |
string |
"note" |
<?php
if ($value === null) {
// ...
}
<?php
if (is_null($value)) {
// ...
}
no-iterator-to-array-in-foreachDetects iterator_to_array() calls used directly as a foreach expression.
Since foreach natively supports any Traversable, wrapping an iterator in
iterator_to_array() is redundant and causes unnecessary memory allocation.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
false |
level |
string |
"warning" |
<?php
foreach ($iterator as $value) {
// ...
}
<?php
foreach (iterator_to_array($iterator) as $value) {
// ...
}
no-noopDetects redundant noop statements.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
echo "Hello, world!";
<?php
;
no-protected-in-finalDetects protected items in final classes or enums.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
final class Foo {
private string $foo;
private(set) string $bar;
private string $baz;
private function fun(): void {
// ...
}
}
<?php
final class Foo {
protected string $foo;
protected(set) string $bar;
protected private(set) string $baz;
protected function fun(): void {
// ...
}
}
no-redundant-binary-string-prefixDetects the redundant b/B prefix on string literals. The binary string prefix
has no effect in PHP and can be safely removed.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
$foo = 'hello';
$bar = "world";
<?php
$foo = b'hello';
$bar = b"world";
no-redundant-blockDetects redundant blocks around statements.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
echo "Hello, world!";
<?php
{
echo "Hello, world!";
}
no-redundant-continueDetects redundant continue statements in loops.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
while (true) {
echo "Hello, world!";
}
<?php
while (true) {
echo "Hello, world!";
continue; // Redundant `continue` statement
}
no-redundant-fileDetects redundant files that contain no executable code or declarations.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
declare(strict_types=1);
function foo(): void {
return 42;
}
<?php
declare(strict_types=1);
// This file is redundant.
no-redundant-finalDetects redundant final modifiers on methods in final classes or enum methods.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
final class Foo {
public function bar(): void {
// ...
}
}
<?php
final class Foo {
final public function bar(): void {
// ...
}
}
no-redundant-issetDetects redundant arguments in isset() calls where a nested access already implies the parent checks.
For example, isset($d, $d['first'], $d['first']['second']) can be simplified to
isset($d['first']['second']) because checking a nested array access or property access
implicitly verifies that all parent levels exist.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
if (isset($d['first']['second'])) {
echo 'all present';
}
<?php
if (isset($d, $d['first'], $d['first']['second'])) {
echo 'all present';
}
no-redundant-labelDetects redundant goto labels that are declared but not used.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
goto end;
echo "Hello, world!";
end:
<?php
label:
echo "Hello, world!";
no-redundant-literal-returnDetects redundant literal guard patterns where an if statement checks if a variable equals a literal and returns that same literal, followed by returning the variable.
This pattern is redundant because if the variable equals the literal, returning the variable would return the same value anyway.
This includes patterns with else clauses and elseif chains where all branches follow the same redundant pattern.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"warning" |
<?php
function getValue($x) {
return $x;
}
function getValueOrDefault($x, $default) {
if ($x === null) {
return $default;
}
return $x;
}
<?php
function getValue($x) {
if ($x === null) {
return null;
}
return $x;
}
function getWithElse($x) {
if ($x === null) {
return null;
} else {
return $x;
}
}
function getWithElseIf($x) {
if ($x === null) {
return null;
} elseif ($x === '') {
return '';
}
return $x;
}
no-redundant-mathDetects redundant mathematical operations that can be simplified or removed. Includes operations like multiplying by 1/-1, adding 0, modulo 1/-1, etc.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
$result = $value * 2;
$sum = 1 + $total;
$difference = $value - 1;
$remainder = $x % 2;
<?php
$result = $value * 1;
$sum = 0 + $total;
$difference = $value - 0;
$remainder = $x % 1;
$negative = $value * -1;
no-redundant-method-overrideDetects methods that override a parent method but only call the parent method with the same arguments.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
class Parent
{
public function foo(): void
{
// ...
}
}
class Child extends Parent
{
public function foo(): void
{
parent::foo();
echo 'Additional logic here';
}
}
<?php
class Parent
{
public function foo(): void
{
// ...
}
}
class Child extends Parent
{
public function foo(): void
{
parent::foo();
}
}
no-redundant-nullsafeFlags the use of the nullsafe operator (?->) in contexts where its null-checking behavior is redundant.
This occurs in two common situations:
?-> is immediately followed by the null coalescing operator (??).?-> is checked with isset().In both scenarios, the surrounding language construct (?? or isset()) already handles null values safely,
making the ?-> operator superfluous and the code unnecessarily verbose.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
$name = $user->name ?? 'Guest';
if (isset($user->profile)) {
// Do something with $user->profile
}
<?php
$name = $user?->name ?? 'Guest';
if (isset($user?->profile)) {
// Do something with $user->profile
}
no-redundant-parenthesesDetects redundant parentheses around expressions.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
$foo = 42;
<?php
$foo = (42);
no-redundant-readonlyDetects redundant readonly modifiers on properties.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
readonly class User
{
public $name;
}
<?php
readonly class User
{
public readonly $name;
}
no-redundant-string-concatDetects redundant string concatenation expressions.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
$foo = "Hello World";
<?php
$foo = "Hello" . " World";
no-redundant-useDetects use statements that import items that are never used or are redundant
because they import from the same namespace.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"warning" |
<?php
namespace App;
use App\Helpers\ArrayHelper;
$result = ArrayHelper::combine([]);
<?php
namespace App;
use App\Helpers\ArrayHelper;
use App\Helpers\StringHelper; // StringHelper is not used.
$result = ArrayHelper::combine([]);
no-redundant-write-visibilityDetects redundant write visibility modifiers on properties.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
final class User
{
public $name;
}
<?php
final class User
{
public public(set) $name;
}
no-redundant-yield-fromDetects redundant use of yield from with single-element array literals.
Using yield from with a single-element array literal creates unnecessary
overhead in the generated opcodes. Direct yield is simpler and more efficient.
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"help" |
<?php
function gen(): Generator {
yield 1;
yield 'foo' => new stdClass();
}
<?php
function gen(): Generator {
yield from [1];
yield from ['foo' => new stdClass()];
}
no-self-assignmentDetects and removes self-assignments where a variable or property is assigned to itself.
Self-assignments have no effect and are typically mistakes or leftover from refactoring. For object properties, the fix is marked as potentially unsafe because reading or writing properties may have side effects through magic methods (__get, __set) or property hooks (PHP 8.4+).
| Option | Type | Default |
|---|---|---|
enabled |
boolean |
true |
level |
string |
"warning" |
<?php
$a = $b;
$this->x = $other->x;
$foo->bar = $baz->bar;
<?php
$a = $a;
$this->x = $this->x;
$foo->bar = $foo->bar;
How can I help you explore Laravel packages today?