Как поднять уровень анализа вашего Laravel-приложения с 0 до 9 в Larastan

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Larastan позволяет найти ошибки в вашем Laravel-приложении еще до его запуска. Он представляет собой обертку PHPStan, предназначенную специально для статического анализа с поддержки всей магии внутри Laravel.

В этой статье я намерен провести вас через все этапы от установки Larastan до достижения 9 уровня, не игнорируя абсолютно никаких правил.

Из README Larastan следует, что для его установки нужно сделать следующее:

  1. Запустить composer require larastan/larastan:^2.0 --dev

  2. Добавить файл phpstan.neon или phpstan.neon.dist в корневой каталог вашего проекта:

includes:
    - vendor/larastan/larastan/extension.neon

parameters:

    paths:
        - app/

    # Level 9 is the highest level
    level: 5

Как вы видите, по умолчанию он настроен 5-й уровень на проверки, но мы изменим его уровень на 0.

Прежде чем продолжить, нам необходимо разобраться, что проверяется Larastan на каждом уровне:

  1. базовые проверки, неизвестные классы, неизвестные функции, неизвестные методы, вызываемые из $this, неправильное количество аргументов, передаваемых этим методам и функциям, никогда неопределенные переменные

  2. потенциально неопределенные переменные, неизвестные магические методы и свойства классов с __call и __get

  3. проверка неизвестных методов во всех выражениях (не только для $this), проверка PHPDocs

  4. возвращаемые типы, типы, назначаемые свойствам

  5. базовая проверка мертвого кода — всегда ложные проверки instanceof и других типов, мертвые ветви else, недостижимый код после return; и т.д.

  6. проверка типов аргументов, передаваемых методам и функциям

  7. отчет об отсутствующих аннотациях типов

  8. отчет о частично неправильных типах объединений — если вы вызываете метод, который существует только для некоторых типов в типе объединения, уровень 7 отрапортует об этом; другие возможные неправильные ситуации

  9. отчет о вызове методов и доступе к свойствам для типов с нулевым значением

  10. более строгое отношение к типу mixed — единственная разрешенная операция, которую вы можете сделать с ним, это передать его другому mixed

Учитывая эти правила, предположим, что у нас есть следующий код (для простоты все находится в одном файле):

Примечание: Приведенный здесь код специально был написан так, чтобы я мог получить ошибки, необходимые для того, чтобы показать вам, как действовать дальше, но некоторые его части могут быть написаны более простыми способами.

declare(strict_types=1);

use App\Http\Controllers\Controller;
use App\Models\Appointment;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;

class User extends Model
{
    public function appointments()
    {
        return $this->hasMany(Appointment::class);
    }
}

class UserDTO
{
    public function __construct(
        public $name,
        public $is_active,
    ) {
    }

    public function toArray()
    {
        return [
            'name' => $this->name,
            'is_active' => $this->is_active,
        ];
    }
}

class ShowUserQuery
{
    public function run($id)
    {
        $this->doSomething();

        return User::query()
            ->with('appointments')
            ->find($id);
    }
}

class UserController extends Controller
{
    public function show($id, ShowUserQuery $query)
    {
        return response()->json($query->run($id)->toArray());
    }

    public function store(Request $request)
    {
        $request->validate([
            'name' => ['required', 'max:250'],
            'is_active' => ['required', 'boolean'],
        ]);

        if (true) {
            return;
        }

        $isActive = $request->input('is_active');

        $userDTO = new UserDTO(
            $request->input('name'),
            $isActive
        );

        $user = User::create($userDTO->toArray());

        return $user;
    }
}

После запуска ./vendor/bin/phpstan analyze мы получаем следующие ошибки:

 22     Call to an undefined method ShowUserQuery::doSomething().  
  24     Relation 'appointments' is not found in User model. 

Чтобы исправить их, нам нужно удалить или определить неопределенный метод и добавить возвращаемый тип для отношения модели, в результате чего мы получим следующее:

class User extends Model
{
    public function appointments(): HasMany
    {
        return $this->hasMany(Appointment::class);
    }
}

class ShowUserQuery
{
    public function run($id)
    {
        return User::query()
            ->with('appointments')
            ->find($id);
    }
}

До 4-го уровня мы не получаем никаких ошибок, потому что в этом случае мы не нарушаем правила уровней 1, 2 и 3. После повышения до уровня 4 мы получаем следующие ошибки:

 43     If condition is always true.                           
  47     Unreachable statement - code above always terminates.

Чтобы решить эту проблему, нам нужно удалить оператор if, расположенный внутри метода store нашего контроллера. После исправления функция приобретет следующий вид:

public function store(Request $request)
{
    $data = $request->validate([
        'name' => ['required', 'max:250'],
        'is_active' => ['required', 'boolean'],
    ]);

    $isActive = $request->input('is_active');

    $userDTO = new UserDTO(
        $request->input('name'),
        $isActive
    );

    $user = User::create($userDTO->toArray());

    return $user;
}

Относительно 5-го уровня все в порядке, но на 6-м уровне мы получаем кучу ошибок:

 13     Method User::appointments() return type with generic class                  
         Illuminate\Database\Eloquent\Relations\HasMany does not specify its types:  
         TRelatedModel                                                               
         						
Источник: https://habr.com/ru/companies/otus/articles/816873/


Интересные статьи

Интересные статьи

Уровень вовлеченности и удовлетворенности персонала напрямую влияет на производительность, качество предоставляемых услуг и уровень текучести кадров. Опросы лояльности и удовлетворенности сотрудников ...
Ваше ортодонтическое лечение врач начинает еще до того, как у вас на зубах появились брекеты. Неочевидный, но, пожалуй, самый важный этап ортодонтического лечения — это диагностика и составление плана...
Основная цель статического анализатора – найти и показать ошибки в коде, чтобы вы могли их исправить. Однако показать ошибки — это не так просто, как кажется на первый взгляд. Есть ряд проблем, с кото...
Ранее мы поговорили о двух открытых библиотеках — для обучения байесовских сетей и идентификации структуры данных, плюс — рассказали о фреймворке для AutoML и библиотеке алгоритмов выбора признаков. С...
Библиотеки .NET Core — один из самых популярных C# проектов на GitHub. Неудивительно, с учётом его широкой известности и используемости. Тем интереснее попробовать выяснить, какие тёмные уголки...