1. Go to this page and download the library: Download hihaho/phpstan-rules library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
use Route; // reported
use Illuminate\Support\Facades\Route; // fine
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Request as RequestFacade;
final class StoreUserController
{
public function __invoke(Request $request): mixed
{
$request->input('name'); // reported (data)
request('id'); // reported (helper)
RequestFacade::boolean('debug'); // reported (facade)
$request->safe()->string('name'); // fine
return $request->validate(['name' => '
namespace App\Services;
$toggle->setActive('name', false); // reported — name the flag: active: false
$toggle?->setActive('name', false); // reported
StaticFlag::toggle('name', false); // reported
new Widget('name', true); // reported
$toggle->setActive('name', active: false); // fine — already named
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
final class Interaction extends Model
{
protected $with = ['chapters']; // reported — eager-loads on every query
protected $with = []; // fine — explicit empty default is a no-op
}
// Load where actually needed:
Interaction::query()->with('chapters')->get();
$interaction->loadMissing('chapters');
enum PortalPdfState: string // reported — has localizationKey(), invisible to the contract
{
use HasLocalization;
}
enum ActionType: int implements BaseActionType // fine — BaseActionType extends the contract
{
use HasLocalization;
}
return new class extends Migration
{
private string $table = 'video_sessions';
public function up(): void
{
Schema::table($this->table, function (Blueprint $table): void {
$table->index('external_learner_id'); // reported — rebuilds the table
$table->string('external_learner_id', 255); // reported — no ->instant()
$table->string('locale', 8)->instant(); // fine — MySQL rejects what it cannot apply instantly
});
DB::statement("ALTER TABLE `{$this->table}` ADD COLUMN `foo` BIGINT NULL"); // reported
DB::statement("ALTER TABLE `{$this->table}` ADD COLUMN `bar` BIGINT NULL, ALGORITHM=INSTANT"); // fine
}
};
$this->addColumn('video_sessions', 'locale', fn (Blueprint $table) => $table->string('locale', 8));
private function addColumn(string $table, string $column, Closure $definition): void
{
if (Schema::hasColumn($table, $column)) {
return;
}
Schema::table($table, $definition); // reported at the call site above
}
/** @return list<int> */
public function ids(Collection $users): array
{
return $users->map(fn (User $user): int => $user->id)->values()->all(); // list<int>, no array_values()
}
public function handle(Request $request): void
{
$video = $request->route('video_id'); // Video — no assert() needed
}
/** @param Builder<User> $query */
public function scopeWithPublishedPosts(Builder $query): void
{
// $q is Builder<Post> — Post::PUBLISHED resolves instead of erroring against base Model.
$query->whereHas('posts', fn (Builder $q) => $q->where(Post::STATUS, Post::PUBLISHED));
}
> // Triggers a return.type error (returns the narrowed builder):
> $query->whereHas('posts', fn (Builder $q) => $q->where(Post::STATUS, Post::PUBLISHED));
>
> // Clean — the closure constrains in place and returns nothing:
> $query->whereHas('posts', function (Builder $q): void {
> $q->where(Post::STATUS, Post::PUBLISHED);
> });
>