Вывод типа PhpStorm PHPDoc: есть ли способ манипулировать массивом и сообщить PhpStorm, что его тип совпадает с исходным массивом?

Пример лучше любого объяснения: допустим, у меня есть следующий код

function arrayToIdMap(array $models) : array
{
    $result = [];
    foreach ($models as $model) {
        /** @var BaseClassWithGetIdMethod $model **/
        $result[$model->getId()] = $model;
    }
    return $result;
}

/** @var Car[] **/
$carList = getCarList();

/** @var Truck[] **/
$truckList = getTruckList();

/** @var Car[] **/
$carMap = arrayToIdMap($carList);

/** @var Truck[] **/
$truckMap = arrayToIdMap($truckList);

Что я хочу сделать, так это автоматически информировать PHP о типах $carMap и $truckMap, чтобы у меня был код, который действует как следующий псевдокод:

/**
 * @param array $$models
 * @return The_Original_Type_Inferred_From_$models
 */
function arrayToIdMap(array $models) : array
{
    $result = [];
    foreach ($models as $model) {
        /** @var BaseClassWithGetIdMethod $model **/
        $result[$model->getId()] = $model;
    }
    return $result;
}

/** @var Car[] **/
$carList = getCarList();

/** @var Truck[] **/
$truckList = getTruckList();

$carMap = arrayToIdMap($carList);
$truckMap = arrayToIdMap($truckList);

// $carMap[$id]->someMethod() will not show error if Car class has the someMethod method and PhpStorm knows $carMap is of type Car[] at this point

Это возможно или нет?

Да. Это можно сделать с помощью расширенной мета-функции PhpStorm (PhpStorm использует ее для стандартных array_xxx функций PHP — посмотрите здесь: github.com/JetBrains/phpstorm-stubs/blob/master/meta/… Это не так. однако используйте PHPDoc - он должен храниться в отдельном файле только для глаз PhpStorm.

LazyOne 21.11.2022 13:05

С PHPDoc ... посмотрите на дженерики ... Вам понадобится плагин Psalm (или это PHPStan?), Включенный для этого AFAIK (даже если вы не используете фактический Psalm) - он включен по умолчанию. jetbrains.com/help/phpstorm/using-psalm.html#generics-suppor‌​t . Также 1) blog.jetbrains.com/phpstorm/2021/12/phpstorm-2021-3-release/‌​… 2) blog.jetbrains.com/phpstorm/2022/08/…

LazyOne 21.11.2022 13:13
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
Socialite Login With Google Account In Laravel 9
Socialite Login With Google Account In Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com.
Обновление драйверов Microsoft ODBC (с 17 до 18) для PHP
Обновление драйверов Microsoft ODBC (с 17 до 18) для PHP
Все знают, что PHP v7.4 потерял поддержку, и наши недавние старые приложения должны обновиться до PHP v8.x. ...
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как создать PHP Image с нуля
Как создать PHP Image с нуля
Сегодня мы создадим PHP Image from Scratch для того, чтобы легко развернуть базовые PHP-приложения. Пожалуйста, имейте в виду, что это разработка для...
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
2
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это можно сделать с помощью расширенной мета-функции PhpStorm (PhpStorm использует ее для стандартных array_xxx функций PHP — посмотрите здесь: https://github.com/JetBrains/phpstorm-stubs/blob/master/meta/ .phpstorm.meta.php#L64

Однако это не использует PHPDoc. Дополнительная информация (расширенные метаданные) должна храниться в отдельном файле только для глаз PhpStorm.

Сделать .phpstorm.meta.php в корне проекта со следующим содержимым:

<?php

namespace PHPSTORM_META {
    override(\arrayToIdMap(0), type(0));
}

Теперь файл с вашим кодом:

<?php
// Defining used classes and functions

class BaseClassWithGetIdMethod {
    private string $id;

    public function getId(): string
    {
        return $this->id;
    }
}

class Car extends BaseClassWithGetIdMethod {
    public function makeCar(){}
}

class Truck extends BaseClassWithGetIdMethod {
    public function makeTruck(){}
}

function arrayToIdMap(array $models) : array
{
    $result = [];
    foreach ($models as $model) {
        /** @var BaseClassWithGetIdMethod $model **/
        $result[$model->getId()] = $model;
    }
    return $result;
}

// Test code

/** @var Car[] $carList **/
$carList = getCarList();

/** @var Truck[] $truckList **/
$truckList = getTruckList();

$carMap = arrayToIdMap($carList);
//$carMap[0]->

$truckMap = arrayToIdMap($truckList);
//$truckMap[0]->

С приведенным выше кодом PhpStorm предоставляет правильные методы:


Если это должно быть через PHPDoc... посмотрите на дженерики.

Для этого вам понадобится включенный плагин Psalm (или это PHPStan?) (даже если вы не используете фактический Psalm), поскольку такая поддержка предоставляется здесь. В любом случае, оба плагина связаны с PhpStorm и включены по умолчанию. https://www.jetbrains.com/help/phpstorm/using-psalm.html#generics-support

Код:

<?php
// Defining used classes and functions

class BaseClassWithGetIdMethod {
    private string $id;

    public function getId(): string
    {
        return $this->id;
    }
}

class Car extends BaseClassWithGetIdMethod {
    public function makeCar(){}
}

class Truck extends BaseClassWithGetIdMethod {
    public function makeTruck(){}
}

/**
 * @template T
 * @param T $models
 * @return T
 */
function arrayToIdMapZ(array $models) : array
{
    $result = [];
    foreach ($models as $model) {
        /** @var BaseClassWithGetIdMethod $model **/
        $result[$model->getId()] = $model;
    }
    return $result;
}

// Test code

/** @var Car[] $carList **/
$carList = getCarList();

/** @var Truck[] $truckList **/
$truckList = getTruckList();

$carMapZ = arrayToIdMapZ($carList);
$truckMapZ = arrayToIdMapZ($truckList);

$carMapZ[0]->
//$truckMapZ[0]->

Вот что я вижу в моем PhpStorm:

Другие вопросы по теме