За последние 24 часа нас посетили 11263 программиста и 803 робота. Сейчас ищут 370 программистов ...

Как вернуть переменную определённого типа из свойства - массива

Тема в разделе "Прочие вопросы по PHP", создана пользователем romt, 25 ноя 2022.

  1. romt

    romt Новичок

    С нами с:
    26 ноя 2020
    Сообщения:
    5
    Симпатии:
    0
    Доброго времени суток!

    Работаю на PHP 7.4 с помощью phpstorm.
    Очень нравится использовать контроль типов. Очень нравится, что phpstorm отслеживает типы и даёт подсказки по свойствам/методам объектов.

    Но если у класса свойство - массив объектов, то подсказки не работают - phpstorm не отслеживает тип.

    Подробнее. Допустим объект класса "Фура", который может перевозить объекты класса "Груз".
    Хочу по очереди получать этот груз.
    Код (Text):
    1. <?php
    2.  
    3. class Cargo        // груз
    4. {
    5.     protected int $id;
    6.     protected string $name;
    7. }
    8.  
    9. class Truck        // Фура (грузовик)
    10. {
    11.    
    12.     protected array $cargoList = [];    // перевозимые грузы
    13.    
    14.     public function addCargo(Cargo $cargo): void
    15.     {
    16.         $this-cargoList[] = $cargo;
    17.     }  
    18.    
    19.     public function getCargoList(): array
    20.     {
    21.         return $this->cargoList;
    22.     }
    23. }
    24.  
    25.  
    26. // основная часть программы
    27.  
    28. // грузовик
    29. $truck = new Truck();
    30.  
    31. // в $truck как-то попадают грузы
    32.  
    33. // перебор грузов для грузовика
    34. foreach($truck->getCargoList() as $cargo)
    35. {
    36.     // $cargo неизвестного типа
    37.     // phpstorm подсказки не ставит
    38. }
    Пробовал использовать генераторы. Генераторы тоже не могут указывать тип возвращаемой переменной.

    Код (Text):
    1. class Truck
    2. {
    3.    
    4.     protected array $cargoList = [];    // перевозимые грузы
    5.    
    6.     public function addCargo(Cargo $cargo): void
    7.     {
    8.         $this-cargoList[] = $cargo;
    9.     }  
    10.    
    11.     public function getNextCargo(): Generator
    12.     {
    13.         foreach ($this->cargoList as $cargo) {
    14.             yield $cargo;
    15.         }
    16.     }
    17. }
    18.  
    19.  
    20. // основная часть программы
    21.  
    22. // перебор грузов для грузовика
    23. foreach($truck->getNextCargo() as $cargo)
    24. {
    25.     // $cargo неизвестного типа
    26.     // phpstorm подсказки не ставит
    27. }
    Я решил проблему перебором идентификаторов, и дополнительным методом получения по идентификатору:
    Код (Text):
    1. class Truck
    2. {
    3.    
    4.     protected array $cargoList = [];    // перевозимые грузы
    5.    
    6.     public function addCargo(Cargo $cargo): void
    7.     {
    8.         $this-cargoList[] = $cargo;
    9.     }  
    10.    
    11.     public function getIdCargoList(): array
    12.     {
    13.         return array_keys($this->cargoList);
    14.     }
    15.    
    16.     public function getCargoById(int $id): Cargo
    17.     {
    18.         return $this->cargoList[$id];
    19.     }
    20. }
    21.  
    22.  
    23. // основная часть программы
    24.  
    25. // перебор грузов для грузовика
    26. foreach($truck->getIdCargoList() as $cargoId)
    27. {
    28.     $cargo = $truck->getCargoById($cargoId);
    29.    
    30.     // $cargo типа Cargo
    31.     // подсказки phpstorm работают
    32. }
    Но мне не нравится использовать дополнительный метод.

    Как вариант обдумывал ещё для свойства $cargoList вместо массива использовать дополнительный класс, но совсем громоздко получается.

    Господа профессионалы, кто пользуется phpstorm, как можно из объекта получать элементы массива/списка/коллекции, понятного для phpstorm типа?
     
  2. Elkaz

    Elkaz Старожил
    Команда форума Модератор

    С нами с:
    26 июн 2006
    Сообщения:
    3.373
    Симпатии:
    0
    Адрес:
    Баку, Азербайджан
    PHP:
    1. /**
    2. * @return array|Cargo[]
    3. */
    4. public function getIdCargoList(): array
    5.     {
    6.         return array_keys($this->cargoList);
    7.     }
     
  3. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    10.817
    Симпатии:
    1.171
    Адрес:
    там-сям
    PHPStorm поймёт такую анотацию: @return array<Cargo>

    Screenshot 2022-12-28 at 16.31.13.png
    --- Добавлено ---
    Если некий класс реализует интерфейс ArrayAccess, как например Collection а Laravel, то к нему тоже можно применять такой трюк:

    @return Collection<Cargo>

    Пока это только подсказки на уровне DocBlock, но PHP уверенно движется в сторону бОльшей типизации, так что когда-нибудь сможем писать буквально func(): Cargo[] или использовать дженерики.
    --- Добавлено ---
    @Elkaz ты так давно не был на форуме, у тебя подпись протухла.
     
  4. romt

    romt Новичок

    С нами с:
    26 ноя 2020
    Сообщения:
    5
    Симпатии:
    0
    Спасибо, работает.