web-dev-qa-db-fra.com

PHP littéral d'objet

En PHP, je peux spécifier assez facilement des littéraux de tableau:

array(
    array("name" => "John", "hobby" => "hiking"),
    array("name" => "Jane", "hobby" => "dancing"),
    ...
)

Mais que faire si je veux un tableau d'objets? Comment spécifier un littéral d'objet en PHP? I.e. en javascript ce serait:

[
    {name: "John", hobby: "hiking"},
    {name: "Jane", hobby: "dancing"}
]
47
TMS

Comme BoltClock l'a mentionné, il n'y a pas d'objet littéral dans PHP, mais vous pouvez le faire en tapant simplement le transtypage des tableaux en objets:

$testArray = array(
    (object)array("name" => "John", "hobby" => "hiking"),
    (object)array("name" => "Jane", "hobby" => "dancing")
);

echo "Person 1 Name: ".$testArray[0]->name;
echo "Person 2 Hobby: ".$testArray[1]->hobby;
75
Tim

À partir de PHP 5.4, vous pouvez également utiliser la syntaxe de tableau abrégé:

$json = [
    (object) ['name' => 'John', 'hobby' => 'hiking'],
    (object) ['name' => 'Jane', 'hobby' => 'dancing'],
];
59
mipa

Comme d'autres l'ont noté, il n'y a pas d'objet littéral en PHP, mais vous pouvez le "simuler" en transformant un tableau en objet.

Avec PHP 5.4, ceci est encore plus concis, car les tableaux peuvent être déclarés entre crochets . Par exemple:

$obj = (object)[
    "foo" => "bar",
    "bar" => "foo",
];

Cela vous donnerait un objet avec les propriétés "foo" et "bar". Cependant, je ne pense pas que cela procure vraiment un avantage important par rapport à l'utilisation de tableaux associatifs. C'est juste une différence de syntaxe.

Pensez à adopter le caractère unique et la "saveur" de toutes les langues que vous utilisez. En JavaScript, les littéraux d'objet sont omniprésents. En PHP, les tableaux associatifs sont fonctionnellement identiques aux littéraux d'objets JavaScript, sont faciles à créer et sont bien compris par les autres programmeurs PHP. Je pense que vous valez mieux utiliser cette "saveur" que d'essayer de lui donner la même syntaxe que la syntaxe littérale d'objet de JavaScript.

8
Josh

Une autre solution consisterait à utiliser la méthode __set_state() magic:

$object = stdClass::__set_state (array (
    'height'   => -10924,
    'color'    => 'purple',
    'happy'    => false,
    'video-yt' => 'AgcnU74Ld8Q'
));

Un peu plus sur la méthode __set_state (), d'où provient-elle et comment est-elle censée être utilisée.

4
Septagram

Si vous souhaitez définir des modules dans le modèle d'objet littéral "tel que JavaScript", vous pouvez procéder comme suit:

$object = (object) [
    'config' => (object) [
        'username' => 'Rob Bennet',
        'email' => '[email protected]'
    ],

    'hello' => function() use(&$object) {
        return "Hello " . $object->config->username . ". ";
    },

    'emailDisplay' => function() use(&$object) {
        return "Your email address is " . $object->config->email;
    },

    'init' => function($options) use(&$object) {
        $object->config = $options;
        $doUsername = $object->hello;
        $doEmail = $object->emailDisplay;
        return $doUsername() . $doEmail();
    }
];

$sayMyInfo = $object->init;

echo $sayMyInfo((object) [
    'username' => 'Logan',
        'email' => '[email protected]'
]);

Dans ce type de scénario modulaire, je choisis généralement le motif de façade , j'aime juste écrire mes appels de la manière suivante:

Module::action()->item;

ou

Post::get()->title;

Aucun de ces modèles ne facilite (voire même parfois) les tests. Mais ceci est juste une preuve de concept. Techniquement, "non", il n'y a pas d'objet littéral en PHP, mais si vous êtes habitué à la syntaxe JavaScript (que je suis plus que PHP), vous pouvez la simuler et le faire. Comme vous pouvez le constater, la situation est plus compliquée dans PHP qu'en JavaScript.

0
Rob Bennet

En PHP, vous devez créer une instance avant de pouvoir utiliser une classe. Bien sûr, vous pouvez placer les instances dans un tableau ultérieurement.

0
pgampe

Si json_decode(json_encode( $array )) ne vous convient pas, vous pouvez utiliser certaines fonctions similaires. Lequel est le plus rapide, je ne sais pas.

function deep_cast_object( $o ){
  return deep_cast_object_ref( $o );
}

function deep_cast_object_ref( & $o ){

  if( is_array( $o ))
    $o = (object)$o;

  if( is_object( $o ))
    foreach( $o as & $v )
      deep_cast_object_ref( $v );

  return $o;
}

$obj = deep_cast_object(array(
  'Fractal' => array(
    'of'    => array(
      'bad' => 'design',
    ),
  ),
));

var_dump( $obj );
0
biziclop

Bien que le casting en tant qu'objet fonctionne correctement sur un seul niveau hiérarchique, il ne va pas en profondeur. En d'autres termes, si nous voulons des objets à tous les niveaux, nous devrions faire quelque chose comme:

$foods = (object)[
  "fruits" => (object)["Apple" => 1, "banana" => 2, "cherry" => 3],
  "vegetables" => (object)["asparagus" => 4, "broccoli" => 5, "carrot" => 6]
];

Cependant, au lieu de faire plusieurs castings en tant qu'objets, nous pouvons envelopper le tout dans un json_encode et un json_decode comme ceci:

$foods = json_decode(json_encode([
  "fruits" => ["Apple" => 1, "banana" => 2, "cherry" => 3],
  "vegetables" => ["asparagus" => 4, "broccoli" => 5, "carrot" => 6]
]));

Cela garantit que c'est un objet au niveau le plus profond.

0
Dave Lampert

Ma manière delittéraux d'objet de style JavaScript dans PHPest la suivante:

Je crée d'abord un tableau associatif comme ceci:

$test = array(
  'name' => "test",
  'exists' => true
);

Alors j'en fais facilement un objet comme celui-ci:

$test = (object)$test;

Maintenant vous pouvez le tester:

echo gettype($test); // "object"
echo $test->name; // "test"