recoded-dev/phpstan-laravel

使用 PHPStan 提高Laravel 静态分析

安装: 5

依赖: 0

建议者: 0

安全: 0

星标: 0

关注者: 0

分支: 0

开放问题: 1

类型:phpstan-extension

dev-main 2024-07-09 20:49 UTC

This package is auto-updated.

Last update: 2024-09-09 21:21:35 UTC


README

帮助 PHPStan 理解 Laravel 魔法。

用法

安装

composer require --dev recoded-dev/phpstan-laravel

可能会询问您是否要信任 phpstan/extension-installer

Do you trust "phpstan/extension-installer" to execute code and wish to enable it now? (writes "allow-plugins" to composer.json) [y,n,d,?]

这是安全的,用于自动将 phpstan-laravel 包包含到 PHPStan 中。如果您不想这样做,您始终可以添加以下片段到您的 phpstan.neon(.dist) 文件中

includes:
    - vendor/recoded-dev/phpstan-laravel/extension.neon

示例

phpstan-laravel 增加了什么?

作用域

它将帮助理解构建器上的作用域。

<?php

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

class Media extends Model
{
    /**
     * Query only images.
     * 
     * @param \Illuminate\Database\Eloquent\Builder<static> $builder
     * @param bool $exceptWebp
     * @return void
     */
    public function scopeImages(Builder $builder, bool $exceptWebp): void
    {
        $builder->where('mime_type', 'LIKE', 'image/%');    
    }
}

Media::query()->images()->count();

将报告

Method Media::images() invoked with 0 parameters, 1 required.

关系查询

它将帮助理解关系查询回调中给出的(自定义)构建器类型是什么

<?php

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Post extends Model
{
    /**
     * Query only thumbnail.
     * 
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<Post, Media>
     */
    public function thumbnail(): BelongsTo
    {
        return $this->belongsTo(Media::class);
    }
}

/**
 * @extends \Illuminate\Database\Eloquent\Builder<Media>
 */
class MediaBuilder extends Builder
{
    // Add custom methods/"scopes" here.
}

class Media extends Model
{
    public function newEloquentBuilder($query): MediaBuilder
    {
        return new MediaBuilder($query);
    }
}

Post::query()
    ->whereHas('thumbnail', function ($builder) {
        \PHPStan\dumpType($builder);
    })
    ->count();

将报告

Dumped type: MediaBuilder

并允许您在自定义构建器上调用方法。

依赖解析

它将帮助理解从容器中解析出的类型

<?php

class MyService
{
    //
}

\PHPStan\dumpType(app());
\PHPStan\dumpType(app(MyService::class));
\PHPStan\dumpType(app('auth'));

将报告

Dumped type: Illuminate\Contracts\Foundation\Application
Dumped type: MyService
Dumped type: Illuminate\Contracts\Auth\Factory

并允许您在自定义构建器上调用方法。

配置

所有配置选项均位于 neon 配置中的 parameters > laravel 下。例如

parameters:
    laravel:
        option: value

自定义容器绑定

当您尝试从容器中解析类字符串时,phpstan-laravel 会自动理解。但如果有基于非类字符串的绑定,它需要了解这些信息才能为您提供正确的类型。

您可以使用以下方式设置此信息

parameters:
    laravel:
        customBindings:
            foo-bar: App\Service\FooBarService

现在以下代码将输出 App\Service\FooBarService

\PHPStan\dumpType(app('foo-bar'));

形态映射

phpstan-laravel 检查您是否在(形态)关系查询(whereHas、whereHasMorph)的回调参数中使用正确的构建器。但是当您使用形态映射时,phpstan-laravel 需要知道这一点。

您可以使用以下方式设置此信息

parameters:
    laravel:
        morphMap:
            media: App\Models\Media

现在以下代码将输出 Illuminate\Database\Eloquent\Builder<App\Models\Media>

$builder->whereHasMorph('model', ['media'], function ($builder) {
    \PHPStan\dumpType($builder);
});

这将使 PHPStan 理解存在哪些作用域,并验证它们的签名。

为什么使用这个而不是 Larastan?

我们绝对没有声称这个包比 Larastan 更好。Larastan 可能比这个包功能更丰富。然而,这个包不会启动您的应用程序,而 Larastan 会这样做。我们认为静态分析最好的部分是代码不会运行。

贡献

对这个包的开发需要测试和静态分析。

在本地验证这些,在安装了开发依赖项后运行以下命令

vendor/bin/phpunit && vendor/bin/phpstan