web-dev-qa-db-fra.com

Assignation de déstructuration en php pour les objets / tableaux associatifs

Dans CoffeeScript, Clojure, ES6 et de nombreux autres langages, nous avons une déstructuration des objets/cartes/etc un peu comme ceci:

obj = {keyA: 'Hello from A', keyB: 'Hello from B'}
{keyA, keyB} = obj

J'ai trouvé la fonction list en php qui vous permet de détruire des tableaux comme ceci:

$info = array('coffee', 'brown', 'caffeine');
list($drink, $color, $power) = $info;

Existe-t-il un moyen de détruire des objets ou des tableaux associatifs en PHP? Si ce n'est pas dans les bibliothèques de base, peut-être que quelqu'un a écrit une fonction d'aide intelligente?

26
Cotten

Pour PHP 7.0 et inférieur, cela dépasse les fonctionnalités de list. Les documents indiquent:

la liste ne fonctionne que sur des tableaux numériques et suppose que les indices numériques commencent à 0.

Une des choses qui pourrait convenir à votre objectif serait la fonction extract() qui importe les variables d'un tableau dans la table des symboles courante. Alors qu'avec list vous pouvez définir explicitement les noms de variables, extract() ne vous donne pas cette liberté.

Extraction d'un tableau associatif

Avec extract, vous pourriez faire quelque chose comme ça:

<?php

$info = [ 'drink' => 'coffee', 'color' => 'brown', 'power' => 'caffeine' ];
extract($info);

var_dump($drink); // string(6) "coffee"
var_dump($color); // string(5) "brown"
var_dump($power); // string(8) "caffeine"

Extraire un objet

Extraire un objet fonctionne presque de la même manière. Puisque extract ne prend qu'un tableau comme argument, nous devons obtenir les propriétés des objets sous forme de tableau. get_object_vars fait cela pour vous. Il renvoie un tableau associatif avec toutes les propriétés publiques comme clé et leurs valeurs comme valeur.

<?php

class User {

    public $name = 'Thomas';

}

$user = new User();
extract( get_object_vars($user) );

var_dump($name); // string(6) "Thomas"

Pièges

extract() n'est pas identique à list car il ne vous permet pas de définir explicitement les noms de variables qui sont exportés vers la table des symboles. Les noms de variable correspondent par défaut aux clés du tableau.

  • list est une construction de langage tandis que extract() est une fonction
  • Il peut arriver que vous remplaciez involontairement des variables que vous avez définies au préalable
  • Vos clés de tableau peuvent être invalides en tant que noms de variables

Avec le paramètre $flags Que vous pouvez passer comme deuxième argument à extract(), vous pouvez influencer le comportement en cas de collision ou de variables invalides. Mais il est toujours important de savoir comment extract() fonctionne et de l'utiliser avec cauton.

Edit: A partir de PHP 7.1 c'est possible:

http://php.net/manual/en/migration71.new-features.php#migration71.new-features.support-for-keys-in-list

Vous pouvez maintenant spécifier des clés dans list (), ou sa nouvelle syntaxe raccourcie []. Cela permet la déstructuration des tableaux avec des clés non entières ou non séquentielles.

https://php.net/manual/en/migration71.new-features.php#migration71.new-features.symmetric-array-destructuring

La syntaxe abrégée du tableau ([]) peut désormais être utilisée pour détruire les tableaux pour les affectations (y compris dans foreach), comme alternative à la syntaxe list () existante, qui est toujours prise en charge.

Par exemple ceci:

$test_arr = ['a' => 1, 'b' => 2];
list('a' => $a, 'b' => $b) = $test_arr;
var_dump($a);
var_dump($b);

Sortira les éléments suivants à partir de 7.1.0

int(1) 
int(2)
36
thpl

J'ai remarqué que la réponse acceptée manquait des exemples qui utilisent la notation abrégée, des problèmes de sécurité avec l'utilisation de l'extraction et des problèmes IDE.

Destruction de tableaux numériques (PHP 7.1)

Depuis PHP 7.1 la destruction de tableaux numériques ( Destruction de tableaux symétriques ) est supportée comme suit:

<?php
$data = [55, 'John', 'UK'];
[$id, $name] = $data; // short-hand (recommended)
list($id, $name) = $data; // long-hand

Notez que vous pouvez manquer des éléments si vous n'en voulez pas.

Destruction de tableaux associatifs (PHP 7.1)

Vous pouvez également effectuer la destruction de tableaux sur des tableaux associatifs ( Prise en charge des clés dans la liste ) comme ceci:

<?php
$data = ['id' => 55, 'firstName' => 'John', 'country' => 'UK']
['id' => $id, 'firstName' => $name] = $data; // short-hand (recommended)
list('id' => $id, 'firstName' => $name) = $data; // long-hand

Notez que vous pouvez manquer des éléments si vous n'en voulez pas. Le nom de la variable peut également être différent du nom de la propriété.

Destruction d'objets (PHP 7.1)

Malheureusement, il n'y a pas de destruction d'objets. Cependant, vous pouvez convertir un objet en un tableau associatif à l'aide de get_object_vars , puis utilisez la destruction de tableaux associatifs.

<?php
class User {
    public $id;
    public $name;
    public $country;
}

$user = new User();
$user->id = 55;
$user->name = 'John';
$user->country = 'UK';

['id' => $id, 'firstName' => $name] = get_object_vars($user)

Cependant, cela peut casser certaines fonctionnalités IDE. Voici quelques problèmes que j'ai remarqués lors de l'utilisation de PHPStorm 2019.1:

  • Les IDE peuvent ne plus comprendre le type des variables, vous devrez donc ajouter un peu de @var Type PHPDocs pour maintenir la fonctionnalité d'auto-complétion
  • Ne fonctionne pas bien avec les outils de refactoring. Par exemple, si vous renommez l'une des propriétés, la partie destructrice de tableau ne sera pas également renommée automatiquement.

Je recommande donc de le faire normalement:

$id = $user->id
$name = $user->firstName

N'utilisez PAS extract

Avec extraire, toutes les variables sont toujours définies. Là, c'est une très mauvaise idée de l'utiliser car:

  • Cela peut entraîner des problèmes de sécurité. Même si vous faites attention, cela peut conduire à des failles de sécurité non évidentes à l'avenir. Si vous l'utilisez, ne l'utilisez pas avec une entrée utilisateur (par exemple $_GET, $_POST), à moins que vous ne vouliez faire une journée de pirate malveillant.
  • Peut entraîner des bogues difficiles à détecter
  • Si la classe ou le tableau change à l'avenir, en introduisant de nouvelles propriétés, il peut casser votre code s'il coïncide avec une variable déjà utilisée, sauf si vous utilisez le EXTR_SKIP drapeau ou similaire
4
Yahya Uddin

Les variables variables sont une façon de procéder. Un foreach vous maintient dans la portée, vous pouvez donc définir vos variables explicitement à partir du tableau comme ceci:

$args = ['a' => 1, 'b' => 2, 'c' => 3];
foreach (['a', 'c'] as $v) $$v = $args[$v];
// $a is 1, $b is undefined, $c is 3

Ce n'est vraiment pas joli, et heureusement, cela a été résolu dans 7.1 par https://wiki.php.net/rfc/short_list_syntax . Cela vous permettrait de dire ['a' => $a, 'c' => $c] = $args; dans l'exemple ci-dessus.

Étant donné que 7.1 inclut un moyen d'utiliser un nom différent pour votre var que la clé de tableau assoc, je mentionnerai que c'est assez simple en utilisant mon approche ici aussi.

foreach (['a' => 'eh', 'b' => 'bee'] as $k => v) $$v = $args[$k];
// $eh is 1, $bee is 2
0
Josh from Qaribou