PHP est un langage de paradigme mixte, permettant d’utiliser et de retourner des types de données non-objets, tels que des tableaux. Je pose une question pour essayer de clarifier certaines lignes directrices pour la sélection de tableaux par rapport à des objets lors du choix de la structure de programmation à utiliser dans une situation donnée.
Il s’agit en réalité de questions sur les moyens de coder des données à l’aide de constructions en langage PHP et sur la manière de choisir un moyen plutôt que l’autre à des fins de transmission de données (architecture orientée services ou services Web, par exemple).
Exemple
Supposons que vous ayez un type d'élément composé de {coût, nom, numéro de pièce, nombre d'élément}. Votre programme appelle à l'affichage de plusieurs de ces types d'élément, à l'endroit où vous décidez d'utiliser un tableau comme conteneur externe pour contenir chacun des types d'élément. [Vous pouvez également utiliser PHP ArrayObject
pour le paradigme OO, mais ma question ne concerne pas ce tableau (externe)]. Ma question porte sur la manière de coder les données de type d'élément et sur le paradigme à utiliser. PHP vous permet d'utiliser PHP Native Arrays
ou PHP Objects
.
Je peux encoder de telles données, de deux manières ici, comme ceci:
//PHP's associative arrays:
$ret = array(
0 => array(
'cost' => 10.00,
'name' => 'item1',
'part_number' => 'zyz-100',
'item_count' => 15
),
1 => array(
'cost' => 34.00,
'name' => 'item2',
'part_number' => 'abc-230',
'item_count' => 42
),
);
contre
//here ItemType is encapsulated into an object
$ret = array(
0 => new ItemType(10.00, 'item1', 'zyz-100', 15),
1 => new ItemType(34.00, 'item2', 'abc-230', 42),
);
class ItemType
{
private $price;
private $name;
private $partNumber;
private $itemCount;
function __construct($price, $name, $partNumber, $itemCount) {..}
}
Ce que je pense
L'encodage de tableau est léger, et plus compatible JSON, mais peut être plus facile à gâcher. Misspell une des clés de tableau associatif et vous pouvez avoir une erreur plus difficile à détecter. Mais il est également plus facile de changer sur un coup de tête. Supposons que je ne souhaite item_count
plus stocker de données , je peux utiliser n’importe quel logiciel de traitement de texte pour supprimer facilement toutes les item_count
instances du tableau, puis mettre à jour les autres fonctions qui l’utilisent en conséquence. C'est peut-être un processus plus fastidieux, mais c'est simple.
Le codage orienté objet fait appel aux fonctionnalités des langages IDE et PHP et facilite la détection préalable des erreurs, mais il est en premier lieu plus difficile de programmer et de coder. Je dis plus fort, car vous devez réfléchir un peu sur vos objets, penser à l’avenir, et le codage en sortie d’objet prend une charge cognitive un peu plus lourde que de taper des structures de tableau. Cela dit, une fois codés, certaines modifications item_count
seront peut-être plus faciles à mettre en œuvre, dans un sens, la suppression , par exemple, nécessitera de modifier moins de lignes de code. Cependant, les changements eux-mêmes peuvent nécessiter une charge cognitive plus importante par rapport à la méthode de la matrice, car des installations OO de niveau supérieur sont impliquées.
Question
Dans certains cas, cela est clair, comme dans les cas où je devrai manipuler les données. Mais dans certains cas, où je n'ai besoin que de stocker quelques lignes de données "Type d'élément", je ne dispose pas de directives ou de considérations claires sur lesquelles s'appuyer lorsque j'essaie de décider d'utiliser des tableaux ou de construire des objets. Il semble que je peux juste lancer une pièce et en choisir une. est-ce le cas ici?
(object)['foo'=>'bar']
. La valeur résultante a classStdClass
, sera codée JSON dans sa totalitéjson_encode()
et les propriétés peuvent être renommées aussi facilement que des index de tableau (ce qui n’est pas toujours aussi facile, lorsqu’il est accédé indirectement via une variable). Cependant, il existe différentes opérations sur ces valeurs; Par exemple, vous n'avez pas de unions d'objets comme vous avez des unions de tableaux et vous ne pouvez pas utiliser directement lesarray_*()
fonctions.array
, 2:User-defined Class
, 3:stdClass
. Les performances en termes de vitesse sont à peu près les mêmes lorsque vous comparezarray
et unUser-defined class
(tel que votreItemType
), mais les définitionsclass
ont tendance à utiliser moins de mémoire que d’utiliserarray
s.stdClass
d'autre part, est la plus lente des trois options et utilise également le plus de mémoire.Réponses:
Selon moi, cela dépend de ce que vous avez l'intention de faire avec les données par la suite. Sur la base de quelques vérifications simples, vous pouvez déterminer laquelle des deux structures de données vous convient le mieux:
Est-ce que ces données sont associées à une logique?
Par exemple, est
$price
stocké sous forme de nombre entier de centimes, donc un produit avec un prix de 9,99 $ auraitprice = 999
et nonprice = 9.99
? (Probablement, oui) OupartNumber
faut-il correspondre à une expression régulière spécifique? Ou avez-vous besoin de pouvoir vérifier facilement si leitemCount
fichier est disponible dans votre inventaire? Aurez-vous besoin de faire ces fonctions à l'avenir? Si c'est le cas, votre meilleur pari est de créer une classe maintenant. Cela signifie que vous pouvez définir des contraintes et une logique intégrées à la structure de données:private $myPrice
est défini sur999
mais$item->getPriceString()
renvoie$9.99
et$item->inStock()
est disponible pour être appelé dans votre application.Allez-vous transmettre ces données à plusieurs fonctions PHP?
Si c'est le cas, utilisez une classe. Si vous générez ces données une fois pour y effectuer des transformations ou simplement pour envoyer des données JSON à une autre application (JavaScript ou autre), un tableau constitue un choix plus simple. Mais si vous avez plus de deux fonctions PHP qui acceptent ces données en tant que paramètre, utilisez une classe. Si rien d'autre, cela vous permet de définir
someFunction(MyProductClass $product) {
et il est très clair ce que vos fonctions attendent en entrée. À mesure que votre code évoluera et que vous disposerez de plus de fonctions, il sera beaucoup plus facile de savoir quel type de données chaque fonction accepte. VoirsomeFunction($someArrayData) {
n'est pas aussi clair. De plus, cela n’impose pas la cohérence des types et signifie que (comme vous l’avez dit) la structure flexible du tableau peut causer des problèmes de développement ultérieurement.Vous construisez une bibliothèque ou une base de code partagée?
Si oui, utilisez un cours! Pensez à un nouveau développeur qui utilise votre bibliothèque ou à un autre développeur quelque part dans l'entreprise qui n'a jamais utilisé votre code auparavant. Il leur sera beaucoup plus facile d'examiner une définition de classe et de comprendre ce que cette classe fait, ou de voir un certain nombre de fonctions de votre bibliothèque qui acceptent des objets d'une certaine classe, plutôt que d'essayer de deviner de quelle structure elles ont besoin pour générer dans une bibliothèque. nombre de tableaux. Cela concerne également les problèmes de cohérence des données avec # 1: si vous développez une bibliothèque ou une base de code partagé, soyez gentil avec vos utilisateurs: donnez-leur des classes qui renforcent la cohérence des données et évitez qu'ils ne commettent des erreurs dans la conception de vos données. .
Est-ce une petite partie d'une application ou simplement une transformation de données? Ne faites-vous pas partie de ce qui précède?
Une classe peut être trop; utilisez un tableau si cela vous convient et que vous le trouvez plus facile. Comme indiqué ci-dessus, si vous ne générez que des données structurées à envoyer au format JSON, YAML, XML ou autre, ne vous embêtez pas avec une classe, sauf en cas de nécessité. Si vous écrivez un petit module dans une application plus grande et qu'aucun autre module / équipe n'a besoin d'interface avec votre code, un tableau suffit peut-être.
En fin de compte, prenez en compte les besoins en mise à l'échelle de votre code et considérez qu'un tableau structuré peut constituer une solution rapide, mais une classe est une solution beaucoup plus résiliente et évolutive.
Prenez également en compte les éléments suivants: si vous avez une classe et que vous souhaitez
json_data()
exporter au format JSON, rien ne vous empêche de définir une méthode de votre classe renvoyant un tableau JSON-ifiable des données de la classe. C'est ce que j'ai fait dans mes applications PHP où je devais envoyer des données de classe au format JSON. Par exemple:la source
my_lineitems
, il est donc inutile de les obtenir par référence, d'autant plus que les variables ne contiennent qu'un identifiant pour l'objet, pas l'objet lui-même. php.net/manual/en/language.oop5.references.phpVous pouvez implémenter la structure json en utilisant l' interface JsonSerializable et utiliser un tableau / classe imbriqué de quelque manière que ce soit. La classe est plus rapide dans les opérations get / set et plus facile à déboguer. Avec Array, vous n'avez besoin d'aucune déclaration.
la source
json_encode(['order'=>$o]);
dans existsing réponse acceptée est vide:{"order":{}}
. Bien sûr, vous pouvez l’utiliser: à$o->forJSON()
chaque fois sur tous les objets, à tous les niveaux, mais son design n’est pas vraiment bon. Parce que tout le temps il faut écrire quelque chose comme:$items_json = array(); foreach($this->my_lineitems as $item) $items_json[] = $item->forJSON();