web-dev-qa-db-fra.com

Quand dois-je utiliser stdClass et quand dois-je utiliser un tableau en code php oo?

Au milieu d'une période de remaniements importants au travail, je souhaite introduire stdClass ***** comme un moyen de renvoyer des données à partir de fonctions et j'essaie de trouver des arguments non subjectifs pour appuyer ma décision.

Y a-t-il des situations où serait-il préférable d'utiliser l'un au lieu de l'autre ??

Quels avantages pourrais-je obtenir à utiliser stdClass au lieu des tableaux ??


Certains diront que les fonctions doivent être aussi petites et spécifiques pour pouvoir renvoyer une seule valeur. Ma décision d'utiliser stdClass est temporelle, car j'espère trouver les bons objets de valeur pour chaque processus à long terme.

68
JonG

L'approche habituelle est

  • Utilisez des objets lors du retour d'une structure de données définie avec des branches fixes:

     $person
       -> name = "John"
       -> surname = "Miller"
       -> address = "123 Fake St"
    
  • Utilisez des tableaux lorsque vous retournez une liste:

      "John Miller"
      "Peter Miller"
      "Josh Swanson"
      "Harry Miller"
    
  • Utilisez un tableau d'objets lors du retour d'une liste d'informations structurées:

      $person[0]
        -> name = "John"
        -> surname = "Miller"
        -> address = "123 Fake St"
    
      $person[1]
        -> name = "Peter"
        -> surname = "Miller"
        -> address = "345 High St"
    

Les objets ne conviennent pas pour contenir des listes de données, car vous avez toujours besoin d'une clé pour les traiter. Les tableaux peuvent remplir les deux fonctions - contenir des listes arbitraires et une structure de données.

Par conséquent, vous pouvez utiliser des tableaux associatifs sur des objets pour les premier et troisième exemples si vous le souhaitez. Je dirais que ce n'est qu'une question de style et de préférence.

@Deceze fait un certain nombre de bons points sur le moment d'utiliser un objet (validation, vérification de type et méthodes futures).

60
Pekka 웃

L'utilisation de stdClass pour remplir la même fonction qu'un tableau n'est pas très utile à mon humble avis, cela ajoute simplement la surcharge d'un objet sans aucun avantage réel. Vous manquez également de nombreuses fonctions de tableau utiles (par exemple array_intersect). Vous devez au moins créer votre propre classe pour activer la vérification de type ou ajouter des méthodes à l'objet pour qu'il soit utile d'utiliser un objet.

41
deceze

Je ne pense pas qu'il y ait un avantage raisonnable à utiliser un stdClass sur un tableau tant que votre seule intention est de renvoyer plusieurs types de données arbitraires à partir d'un appel de fonction .

Comme vous ne pouvez techniquement pas retourner plusieurs valeurs nativement, vous devez utiliser un conteneur qui peut contenir tous les autres types de données disponibles en PHP. Ce serait soit un objet, soit un tableau.

function fn1() { return array(1,2); }
function fn2() { return array('one' => 1, 'two' => 2); }
function fn3() { return (object) array(1,2); }
function fn4() { return (object) array('one' => 1, 'two' => 2); }

Tout ce qui précède fonctionnerait. Le tableau est une fraction infime négligeable plus rapide et moins de travail à taper. Il a également un objectif clairement défini contrairement à la stdClass générique (qui est un peu radicale, n'est-ce pas). Les deux n'ont qu'une interface implicite, vous devrez donc regarder les documents ou le corps de la fonction pour savoir ce qu'ils contiendront.

Si vous souhaitez utiliser des objets à tout prix, vous pouvez utiliser ArrayObject ou SplFixedArray , mais si vous regardez leurs API, diriez-vous que vous avez besoin de leurs fonctionnalités pour la tâche simple de renvoyer des valeurs multiples aléatoires? Je ne pense pas. Ne vous méprenez pas: si vous voulez utiliser stdClass, alors utilisez-le. Ce n'est pas comme si ça cassait quoi que ce soit. Mais vous ne gagneriez rien non plus. Pour ajouter au moins un avantage, vous pouvez créer une classe distincte nommée ReturnValues ​​pour cela.

Peut être une simple classe de marquage

class ReturnValues {}

ou quelque chose de plus fonctionnel

class ReturnValues implements Countable
{
    protected $values;
    public function __construct() { $this->values = func_get_args(); }
    public function __get($key) return $this->values[$key]; }
    public function count() { return count($this->values); }
}

Certes, cela ne fait pas grand-chose et en extraire les valeurs se fait toujours via une interface implicite, mais au moins la classe a maintenant une responsabilité plus clairement définie. Vous pouvez étendre cette classe pour créer des objets ReturnValue pour des opérations particulières et leur donner une interface explicite:

class FooReturnValues extends ReturnValues
{
    public function getFoo() { return $this->values['foo']; }
    public function getBar() { return $this->values['foo']; }
}

Maintenant, le développeur n'a qu'à regarder l'API pour savoir quelles valeurs multiples foo () renverra. Bien sûr, devoir écrire des classes ReturnValue concrètes pour chaque opération qui pourrait retourner plusieurs valeurs pourrait devenir fastidieux rapidement. Et personnellement, je trouve cela trop ingénieux pour le but initial.

Quoi qu'il en soit, j'espère que cela a un sens.

18
Gordon

Eh bien, il y a 3 différences:

  • ils ont une identité. c'est pourquoi la valeur par défaut pour la transmission des arguments de tableau est appel par valeur et pour les objets appel par partage.
  • il y a une différence sémantique. Si vous utilisez un objet, quiconque lit le code comprend que la valeur représente le modèle une sorte de droit, tandis qu'un tableau est censé agir comme une collection ou une carte
  • Enfin, le refactoring devient nettement plus facile. Si vous souhaitez utiliser une classe concrète plutôt que stdClass, tout ce que vous avez à faire est d'instancier une autre classe. Ce qui vous permet également d'ajouter des méthodes.

greetz
back2dos

4
back2dos

Le seul vote de confiance OBJECTIF que je puisse trouver est:

json_decode utilise stdClass par défaut, donc les mortels des pays utilisateurs devraient utiliser stdClass pour des situations similaires.

2
William Entriken

Je trouve les objets stdClass sur les tableaux utiles lorsque j'ai besoin de garder mon code propre et quelque peu lisible comme une phrase. Prenons par exemple la fonction getProperties() qui renvoie un ensemble de propriétés, par exemple des données sur une personne (nom, âge, sexe). Si getProperties() renverrait un tableau associatif, lorsque vous souhaitez utiliser l'une des propriétés renvoyées, vous écririez deux instructions:

$data = getProperties();
echo $data['name'];

D'un autre côté, si getProperties() retourne un stdClass alors vous pouvez l'écrire en une seule instruction:

echo getProperties()->name;
1
Cojocariu Adrian

Dans les tests de tableau vs stdclass, la façon dont php gère les propriétés dynamiques est plus lente que les tableaux associatifs. Je ne dis pas cela pour argumenter la micro-optimisation mais plutôt si vous allez le faire, il vaut mieux définir une classe de données sans méthodes et définir des propriétés publiques. Surtout si vous utilisez php 5.4+. Sous le capot, les propriétés définies sont mappées directement à un tableau c sans table de hachage, alors que les dynamiques doivent utiliser une table de hachage.

Cela a l'avantage supplémentaire de devenir plus tard une classe complète sans aucun remaniement majeur de l'interface.

1
bgrohs