Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Mago Laravel Package

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).

View on GitHub
Deep Wiki
Context7

title: BestPractices rules

BestPractices rules

This document details the rules available in the BestPractices category.

Rule Code
Combine Consecutive Issets combine-consecutive-issets
Final Controller final-controller
Loop Does Not Iterate loop-does-not-iterate
Middleware In Routes middleware-in-routes
No Array Accumulation In Loop no-array-accumulation-in-loop
No Direct Database Queries no-direct-db-query
No ini_set no-ini-set
No Inline no-inline
No Parameter Shadowing no-parameter-shadowing
No Sprintf Concat no-sprintf-concat
Prefer Anonymous Migration prefer-anonymous-migration
Prefer Arrow Function prefer-arrow-function
Prefer Early Continue prefer-early-continue
Prefer First Class Callable prefer-first-class-callable
Prefer Interface prefer-interface
Prefer Pre-Increment prefer-pre-increment
Prefer Static Closure prefer-static-closure
Prefer Test Attribute prefer-test-attribute
Prefer View Array prefer-view-array
Prefer While Loop prefer-while-loop
Psl Array Functions psl-array-functions
Psl Data Structures psl-data-structures
Psl DateTime psl-datetime
Psl Math Functions psl-math-functions
Psl Output psl-output
Psl Randomness Functions psl-randomness-functions
Psl Regex Functions psl-regex-functions
Psl Sleep Functions psl-sleep-functions
Psl String Functions psl-string-functions
Require Namespace require-namespace
Single Class Per File single-class-per-file
Sorted Integer Keys sorted-integer-keys
Use Compound Assignment use-compound-assignment
Use WordPress API Functions use-wp-functions
Yoda Conditions yoda-conditions

combine-consecutive-issets

Suggests combining consecutive calls to isset() when they are joined by a logical AND.

For example, isset($a) && isset($b) can be turned into isset($a, $b), which is more concise and avoids repeated function calls. If one or both isset() calls are wrapped in parentheses, the rule will still warn, but it will not attempt an automated fix.

Configuration

Option Type Default
enabled boolean true
level string "warning"

Examples

Correct code

<?php

if (isset($a, $b)) {
    // ...
}

Incorrect code

<?php

if (isset($a) && isset($b)) {
    // ...
}

final-controller

Enforces that controller classes are declared as final.

In modern MVC frameworks, controllers should be treated as entry points that orchestrate the application's response to a request. They are not designed to be extension points.

Extending controllers can lead to deep inheritance chains, making the codebase rigid and difficult to maintain. It's a best practice to favor composition (injecting services for shared logic) over inheritance.

If a controller is intended as a base for others, it should be explicitly marked as abstract. All other concrete controllers should be final to prevent extension.

Requirements

  • Integrations, any of:
    • Symfony
    • Laravel
    • Tempest
    • Spiral
    • CakePHP
    • Yii

Configuration

Option Type Default
enabled boolean true
level string "error"

Examples

Correct code

<?php

namespace App\Http\Controllers;

final class UserController
{
    // ...
}

Incorrect code

<?php

namespace App\Http\Controllers;

class UserController
{
    // ...
}

loop-does-not-iterate

Detects loops (for, foreach, while, do-while) that unconditionally break or return before executing even a single iteration. Such loops are misleading or redundant since they give the impression of iteration but never actually do so.

Configuration

Option Type Default
enabled boolean true
level string "warning"

Examples

Correct code

<?php

for ($i = 0; $i < 3; $i++) {
    echo $i;
    if ($some_condition) {
        break; // This break is conditional.
    }
}

Incorrect code

<?php

for ($i = 0; $i < 3; $i++) {
    break; // The loop never truly iterates, as this break is unconditional.
}

middleware-in-routes

This rule warns against applying middlewares in controllers.

Middlewares should be applied in the routes file, not in the controller.

Requirements

  • Integration: Laravel

Configuration

Option Type Default
enabled boolean true
level string "warning"

Examples

Correct code

<?php

// routes/web.php
Route::get('/user', 'UserController@index')->middleware('auth');

Incorrect code

<?php

namespace App\Http\Controllers;

class UserController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }
}

no-array-accumulation-in-loop

Detects O(n²) array accumulation patterns inside loops.

Calling array_merge(), array_merge_recursive(), array_unique(), or array_values() on an accumulator inside a loop copies the entire array on every iteration. Similarly, using spread syntax ([...$result, ...$item]) in a reassignment has the same cost.

Collect items first and transform once after the loop instead.

Configuration

Option Type Default
enabled boolean false
level string "warning"

Examples

Correct code

<?php

$chunks = [];
foreach ($items as $item) {
    $chunks[] = $item;
}
$result = array_merge(...$chunks);

Incorrect code

<?php

$result = [];
foreach ($items as $item) {
    $result = array_merge($result, $item);
}

no-direct-db-query

This rule flags all direct method calls on the global $wpdb object. Direct database queries bypass the WordPress object cache, which can lead to poor performance. Using high-level functions like get_posts() is safer and more efficient.

Requirements

  • Integration: WordPress

Configuration

Option Type Default
enabled boolean true
level string "warning"

Examples

Correct code

<?php

$posts = get_posts(['author' => $author_id]);

Incorrect code

<?php

global $wpdb;
$posts = $wpdb->get_results("SELECT * FROM {$wpdb->posts} WHERE post_author = 1");

no-ini-set

Enforces that ini_set is not used.

Runtime configuration changes via ini_set make application behavior unpredictable and environment-dependent. They can mask misconfigured servers, introduce subtle bugs, and lead to inconsistent behavior between development, testing, and production environments.

Modern applications should rely on well-defined configuration through php.ini or framework specific configuration. This ensures that configuration is explicit, consistent, and controlled across all environments.

If a setting truly needs to vary between contexts, it should be handled at the infrastructure or framework configuration level, never by calling ini_set within the application code.

Configuration

Option Type Default
enabled boolean true
level string "warning"

Examples

Correct code

<?php

// In framework config files (e.g., wp-config.php), use constants.
define( 'WP_DEBUG', true );

// Use framework-provided functions where available.
wp_raise_memory_limit( 'admin' );

Incorrect code

<?php

// This can override server settings in an unpredictable way.
ini_set( 'display_errors', 1 );
ini_set( 'memory_limit', '256M' );

no-inline

Disallows inline content (text outside of PHP tags) in source files.

Most modern PHP applications are source-code only and do not use PHP as a templating language. Inline content before <?php, after ?>, or between PHP tags is typically unintentional and can cause issues such as unexpected output or "headers already sent" errors.

This rule is disabled by default and is intended for codebases that do not use PHP templates.

Configuration

Option Type Default
enabled boolean false
level string "error"

Examples

Correct code

<?php

namespace App;

echo "Hello, world!";

Incorrect code

Hello
<?php

echo "Hello, world!";

?>
Goodbye

no-parameter-shadowing

Detects when a function or method parameter is shadowed by a loop variable or catch variable, making the original parameter value inaccessible.

Configuration

Option Type Default
enabled boolean false
level string "warning"

Examples

Correct code

<?php

function read(array $domains, array $locales): void
{
    $translations = getTranslations($domains, $locales);

    foreach ($translations as $namespace => $namespaceLocales) {
        // $locales is still accessible
    }
}

Incorrect code

<?php

function read(array $domains, array $locales): void
{
    $translations = getTranslations($domains, $locales);

    foreach ($translations as $namespace => $locales) {
        // $locales now refers to the loop value, original argument is lost
    }
}

no-sprintf-concat

Disallows string concatenation with the result of an sprintf call.

Concatenating with sprintf is less efficient and can be less readable than incorporating the string directly into the format template. This pattern creates an unnecessary intermediate string and can make the final output harder to see at a glance.

Configuration

Option Type Default
enabled boolean true
level string "warning"

Examples

Correct code

<?php

$name = 'World';
$greeting = sprintf('Hello, %s!', $name);

Incorrect code

<?php

$name = 'World';
$greeting = 'Hello, ' . sprintf('%s!', $name);

prefer-anonymous-migration

Prefer using anonymous classes for Laravel migrations instead of named classes. Anonymous classes are more concise and reduce namespace pollution, making them the recommended approach for migrations.

Requirements

  • Integration: Laravel

Configuration

Option Type Default
enabled boolean true
level string "warning"

Examples

Correct code

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
    public function up(): void {
        Schema::create('flights', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('airline');
            $table->timestamps();
        });
    }

    public function down(): void {
        Schema::drop('flights');
    }
};

Incorrect code

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class MyMigration extends Migration {
    public function up(): void {
        Schema::create('flights', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('airline');
            $table->timestamps();
        });
    }

    public function down(): void {
        Schema::drop('flights');
    }
}

return new MyMigration();

prefer-arrow-function

Promotes the use of arrow functions (fn() => ...) over traditional closures (function() { ... }).

This rule identifies closures that consist solely of a single return statement and suggests converting them to arrow functions.

Requirements

  • PHP version: >= 7.4.0

Configuration

Option Type Default
enabled boolean true
level string "help"

Examples

Correct code

<?php

$a = fn($x) => $x + 1;

Incorrect code

<?php

$a = function($x) {
    return $x + 1;
};

prefer-early-continue

Suggests using early continue pattern when a loop body contains only a single if statement.

This improves code readability by reducing nesting and making the control flow more explicit.

Configuration

Option Type Default
enabled boolean true
level string "help"
max_allowed_statements integer 0

Examples

Correct code

<?php

for ($i = 0; $i < 10; $i++) {
    if (!$condition) {
        continue;
    }
    doSomething();
}

Incorrect code

<?php

for ($i = 0; $i < 10; $i++) {
    if ($condition) {
        doSomething();
    }
}

prefer-first-class-callable

Promotes the use of first-class callable syntax (...) for creating closures.

This rule identifies closures and arrow functions that do nothing but forward their arguments to another function or method. In such cases, the more concise and modern first-class callable syntax, introduced in PHP 8.1, can be used instead. This improves readability by reducing boilerplate code.

By default, this rule only checks method and static method calls. Optionally, function calls can also be checked by enabling check-functions, but this may produce false positives with internal PHP functions that enforce strict argument counts.

Requirements

  • PHP version: >= 8.1.0

Configuration

Option Type Default
enabled boolean true
level string "warning"
check-functions boolean false

Examples

Correct code

<?php

$names = ['Alice', 'Bob', 'Charlie'];
$uppercased_names = array_map($formatter->format(...), $names);

Incorrect code

<?php

$names = ['Alice', 'Bob', 'Charlie'];
$uppercased_names = array_map(fn($name) => $formatter->format($name), $names);

prefer-interface

Detects when an implementation class is used instead of the interface.

Requirements

  • Integration: Symfony

Configuration

Option Type Default
enabled boolean true
level string "note"

Examples

Correct code

<?php

use Symfony\Component\Serializer\SerializerInterface;

class UserController
{
    public function __construct(SerializerInterface $serializer)
    {
        $this->serializer = $serializer;
    }
}

Incorrect code

<?php

use Symfony\Component\Serializer\Serializer;

class UserController
{
    public function __construct(Serializer $serializer)
    {
        $this->serializer = $serializer;
    }
}

prefer-pre-increment

Enforces the use of pre-increment (++$i) and pre-decrement (--$i) over post-increment ($i++) and post-decrement ($i--).

Pre-increment is marginally more efficient and is the convention used by the Symfony coding standards.

Requirements

  • Integration: Symfony

Configuration

Option Type Default
enabled boolean false
level string "help"

Examples

Correct code

<?php

++$i;
--$count;

Incorrect code

<?php

$i++;
$count--;

prefer-static-closure

Suggests adding the static keyword to closures and arrow functions that don't use $this.

Static closures don't bind $this, making them more memory-efficient and their intent clearer.

Configuration

Option Type Default
enabled boolean true
level string "help"

Examples

Correct code

<?php

class Foo {
    public function bar() {
        // Static closure - doesn't use $this
        $fn = static fn($x) => $x * 2;

        // Non-static - uses $this
        $fn2 = fn() => $this->doSomething();

        // Static function - doesn't use $this
        $closure = static function($x) {
            return $x * 2;
        };
    }
}

Incorrect code

<?php

class Foo {
    public function bar() {
        // Missing static - doesn't use $this
        $fn = fn($x) => $x * 2;

        // Missing static - doesn't use $this
        $closure = function($x) {
            return $x * 2;
        };
    }
}

prefer-test-attribute

Suggests using PHPUnit's #[Test] attribute instead of the test method name prefix.

When a method name starts with test, it can be replaced with a #[Test] attribute and a shorter method name. This is the modern PHPUnit style (PHPUnit 10+).

Requirements

  • Integration: PHPUnit

Configuration

Option Type Default
enabled boolean false
level string "warning"

Examples

Correct code

<?php

use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\Test;

class UserTest extends TestCase
{
    #[Test]
    public function itReturnsFullName(): void {}
}

Incorrect code

<?php

use PHPUnit\Framework\TestCase;

class UserTest extends TestCase
{
    public function testItReturnsFullName(): void {}
}

prefer-view-array

Prefer passing data to views using the array parameter in the view() function, rather than chaining the with() method.`

Using the array parameter directly is more concise and readable.

Requirements

  • Integration: Laravel

Configuration

Option Type Default
enabled boolean true
level string "help"

Examples

Correct code

<?php

return view('user.profile', [
    'user' => $user,
    'profile' => $profile,
]);

Incorrect code

<?php

return view('user.profile')->with([
    'user' => $user,
    'profile' => $profile,
]);

prefer-while-loop

Suggests using a while loop instead of a for loop when the for loop does not have any initializations or increments. This can make the code more readable and concise.

Configuration

Option Type Default
enabled boolean true
level string "note"

Examples

Correct code

<?php

while ($i < 10) {
    echo $i;

    $i++;
}

Incorrect code

<?php

for (; $i < 10;) {
    echo $i;

    $i++;
}

psl-array-functions

This rule enforces the usage of Psl array functions over their PHP counterparts. Psl array functions are preferred because they are type-safe and provide more consistent behavior.

Requirements

  • Integration: Psl

Configuration

Option Type Default
enabled boolean true
level string "warning"

Examples

Correct code

<?php

$filtered = Psl\Vec\filter($xs, fn($x) => $x > 2);

Incorrect code

<?php

$filtered = array_filter($xs, fn($x) => $x > 2);

psl-data-structures

This rule enforces the usage of Psl data structures over their SPL counterparts.

Psl data structures are preferred because they are type-safe and provide more consistent behavior.

Requirements

  • Integration: Psl

Configuration

Option Type Default
enabled boolean true
level string "warning"

Examples

Correct code

<?php

declare(strict_types=1);

use Psl\DataStructure\Stack;

$stack = new Stack();

Incorrect code

<?php

declare(strict_types=1);

$stack = new SplStack();

psl-datetime

This rule enforces the usage of Psl DateTime classes and functions over their PHP counterparts.

Psl DateTime classes and functions are preferred because they are type-safe and provide more consistent behavior.

Requirements

  • Integration: Psl

Configuration

Option Type Default
enabled boolean true
level string "warning"

Examples

Correct code...

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport