94 votes

Indication du type de retour d'une fonction pour un tableau d'objets en PHP7

Je suis très heureux des nouvelles fonctionnalités de PHP 7. Mais je ne sais pas comment retourner un tableau d'objets en PHP 7.

Par exemple, nous avons une classe Item et nous voulons retourner un tableau d'objets de cette classe à partir de notre fonction :

function getItems() : Item[] {
}

Mais cela ne fonctionne pas de cette manière.

109voto

mike Points 580

Vous pouvez taper des indices de cette manière en utilisant docblocks .

Un éditeur PHP (IDE) comme PhpStorm supporte très bien cela et résoudra correctement la classe lors de l'itération sur un tel tableau.

/**
 * @return YourClass[]
 */
public function getObjects(): iterable

PHPStorm supporte également les tableaux imbriqués :

/**
 * @return YourClass[][]
 */
public function getObjects(): iterable

Les versions plus récentes de PHPStorm supportent le format phpstan/psalm :

/**
 * @return array<int, YourObject>
 */
public function getObjects(): array

2 votes

Yep, également soutenu par phpactor

3 votes

Fonctionne également dans NetBeans.

4 votes

Pour info, cela ne fonctionne pas avec VSCode + l'extension Intelliphense.

90voto

Johnny Points 1000

Je comprends ce que vous voulez dire, mais la réponse est malheureusement que vous ne pouvez pas faire cela. PHP7 n'a pas ce genre d'expressivité, donc vous pouvez soit déclarer que votre fonction renvoie "array" (un tableau générique) ou vous devez créer une nouvelle classe ItemArray qui est un tableau d'éléments (mais cela signifie que vous devrez le coder vous-même).

Il n'y a actuellement aucun moyen d'exprimer "Je veux un tableau d'éléments" instances.

EDIT : En guise de référence supplémentaire, voici l' "réseau de" RFC de ce que vous vouliez faire, il a été refusé pour diverses raisons.

21 votes

Je pensais que le passage à PHP 7 pourrait m'aider à créer un code de typage strict :/

1 votes

Je sais, c'est décevant :( J'ai ajouté une référence à la RFC qui parle exactement de la fonctionnalité que vous avez demandée. Elle a été refusée.

1 votes

@Johnny , je ne comprends pas la méthode de vote rfc de PHPs, il n'y a pas de raisonnement derrière pourquoi ils refusent juste des choses sans un deuxième regard, le vote direct n'est pas un bon système pour cela.

13voto

Ruslan Osmanov Points 13305

La version actuelle de PHP ne supporte pas d'indication de type intégrée pour les fichiers de type un tableau d'objets car il n'existe pas de type de données tel que "un tableau d'objets". Un nom de classe peut être interprété comme un type dans certains contextes, ainsi que array mais pas les deux à la fois.

En fait, vous pouvez mettre en œuvre ce type d'indication stricte des types en créant une classe basée sur le modèle ArrayAccess l'interface, par exemple :

class Item
{
    protected $value;

    public function __construct($value)
    {
        $this->value = $value;
    }
}

class ItemsArray implements ArrayAccess
{
    private $container = [];

    public function offsetSet($offset, $value)
    {
        if (!$value instanceof Item) {
            throw new Exception('value must be an instance of Item');
        }

        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }

    public function offsetExists($offset)
    {
        return isset($this->container[$offset]);
    }

    public function offsetUnset($offset)
    {
        unset($this->container[$offset]);
    }

    public function offsetGet($offset)
    {
        return isset($this->container[$offset]) ? $this->container[$offset] : null;
    }
}

function getItems() : ItemsArray
{
    $items = new ItemsArray();
    $items[0] = new Item(0);
    $items[1] = new Item(2);
    return $items;
}

var_dump((array)getItems());

Sortie

array(2) {
  ["ItemsArrayitems"]=>
  array(0) {
  }
  ["container"]=>
  array(2) {
    [0]=>
    object(Item)#2 (1) {
      ["value":protected]=>
      int(0)
    }
    [1]=>
    object(Item)#3 (1) {
      ["value":protected]=>
      int(2)
    }
  }
}

1 votes

C'est une bonne chose, mais je préfère une méthode automatique, j'espère qu'ils implémenteront cette fonctionnalité dans un futur proche, merci :)

0 votes

Merci. J'ai remarqué une chose. Devrait-on dire private $container = [] ; au lieu de private $items = [] ; ?

0 votes

@kta, vous avez raison. J'ai modifié la réponse. Merci.

1voto

safrazik Points 1233

Ce n'est pas possible pour le moment. Mais vous pouvez obtenir le comportement souhaité avec une classe de tableau personnalisée.

function getItems() : ItemArray {
  $items = new ItemArray();
  $items[] = new Item();
  return $items;
}

class ItemArray extends \ArrayObject {
    public function offsetSet($key, $val) {
        if ($val instanceof Item) {
            return parent::offsetSet($key, $val);
        }
        throw new \InvalidArgumentException('Value must be an Item');
    }
}

Merci à la réponse de l'évêque ici

-3voto

Kitiara Points 48

Je crois que c'est ce que vous recherchez

<?php
class C {}

function objects()
{
    return array (new C, new C, new C);
}
list ($obj1, $obj2, $obj3) = objects();

var_dump($obj1);
var_dump($obj2);
var_dump($obj3);
?>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X