Créer des objets anonymes en PHP

141

Comme nous le savons, créer des objets anonymes en JavaScript est facile, comme le code ci-dessous:

var object = { 
    p : "value", 
    p1 : [ "john", "johnny" ]
};

alert(object.p1[1]);

Production:

an alert is raised with value "johnny"

Cette même technique peut-elle être appliquée en PHP? Peut-on créer des objets anonymes en PHP?

Sujit Agarwal
la source
1
Remarque: il s'agit d'une ancienne question, donc la réponse acceptée est obsolète. Cette fonctionnalité demandée a maintenant été ajoutée à PHP 7. Voir la réponse ci-dessous par @ Rizier123.
Simba
@Simba - Merci de l'avoir signalé. Souhaitez-vous publier une réponse sur StackOverflow ici sur cette page pour aider les futurs visiteurs?
Sujit Agarwal
1
Je n'en ai pas besoin; il y a déjà une réponse avec cette info (voir ci-dessous, par @ Rizier123).
Simba

Réponses:

40

Cela fait quelques années, mais je pense que je dois garder les informations à jour!

Depuis PHP 7, il est possible de créer des classes anonymes, vous pouvez donc faire des choses comme ceci:

<?php

    class Foo {}
    $child = new class extends Foo {};

    var_dump($child instanceof Foo); // true

?>

Vous pouvez en savoir plus à ce sujet dans le manuel

Mais je ne sais pas à quel point il est implémenté avec JavaScript, il peut donc y avoir quelques différences entre les classes anonymes en JavaScript et PHP.

Rizier123
la source
@risyasin Merci, mis à jour la réponse et y mettre le lien manuel.
Rizier123
Marquer votre réponse comme correcte pour suivre les dernières modifications de php7. Merci @ Rizier123
Sujit Agarwal
3
C'est intéressant mais cela ne répond pas vraiment à la question, car l'OP demandait un moyen pratique d'initialiser un objet avec différents membres sans créer de classe. Je ne sais pas si des classes anonymes en php peuvent être utilisées pour le faire, et si c'est possible, vous n'avez pas expliqué comment.
amh15
228

"Anonyme" n'est pas la bonne terminologie pour parler d'objets. Il vaudrait mieux dire "objet de type anonyme ", mais cela ne s'applique pas à PHP.

Tous les objets en PHP ont une classe. La classe "par défaut" est stdClass, et vous pouvez en créer des objets de cette façon:

$obj = new stdClass;
$obj->aProperty = 'value';

Vous pouvez également tirer parti de la conversion d'un tableau en objet pour une syntaxe plus pratique:

$obj = (object)array('aProperty' => 'value');
print_r($obj);

Cependant, sachez que la conversion d'un tableau en objet est susceptible de donner des résultats "intéressants" pour ces clés de tableau qui ne sont pas des noms de variables PHP valides - par exemple, voici une de mes réponses qui montre ce qui se passe lorsque les clés commencent par des chiffres.

Jon
la source
1
puis-je également pousser plusieurs tableaux à valeurs?
Sujit Agarwal
2
@CodingFreak: Vous pouvez, mais : si le tableau contient des sous-tableaux et que vous voulez que ceux-ci soient également des objets, vous devrez convertir chacun d'eux en objet explicitement.
Jon
21

Oui c'est possible! Utilisation de cette simple classe d' objet anonyme PHP . Comment ça fonctionne:

// define by passing in constructor
$anonim_obj = new AnObj(array(
    "foo" => function() { echo "foo"; }, 
    "bar" => function($bar) { echo $bar; } 
));

$anonim_obj->foo(); // prints "foo"
$anonim_obj->bar("hello, world"); // prints "hello, world"

// define at runtime
$anonim_obj->zoo = function() { echo "zoo"; };
$anonim_obj->zoo(); // prints "zoo"

// mimic self 
$anonim_obj->prop = "abc";
$anonim_obj->propMethod = function() use($anonim_obj) {
    echo $anonim_obj->prop; 
};
$anonim_obj->propMethod(); // prints "abc"

Bien sûr, cet objet est une instance de AnObjclasse, il n'est donc pas vraiment anonyme, mais il permet de définir des méthodes à la volée, comme le fait JavaScript.

Mihailoff
la source
Vous pouvez utiliser create_function pour émuler une fonction anonyme.
Mihailoff du
Je pense qu'il voulait juste une manière soignée d'initialiser un objet stdClass avec certaines valeurs. Pouvez-vous faire cela avec votre approche?
amh15
18

Jusqu'à récemment, c'est ainsi que je créais des objets à la volée.

$someObj = json_decode("{}");

Ensuite:

$someObj->someProperty = someValue;

Mais maintenant je vais avec:

$someObj = (object)[];

Puis comme avant:

$someObj->someProperty = someValue;

Bien sûr, si vous connaissez déjà les propriétés et les valeurs, vous pouvez les définir à l'intérieur comme cela a été mentionné:

$someObj = (object)['prop1' => 'value1','prop2' => 'value2'];

NB: Je ne sais pas sur quelles versions de PHP cela fonctionne, vous devez donc en être conscient. Mais je pense que la première approche (qui est également courte s'il n'y a pas de propriétés à définir lors de la construction) devrait fonctionner pour toutes les versions qui ont json_encode / json_decode

Zuks
la source
1
En quoi est-ce différent de passer à $ someObj = new \ stdClass ()?
JamesNZ
9

Convertir le tableau en objet (mais ce n'est pas récursif pour les sous-enfants):

$obj = (object)  ['myProp' => 'myVal'];
T.Todua
la source
7

Si vous souhaitez imiter JavaScript, vous pouvez créer une classe Object, et ainsi obtenir le même comportement. Bien sûr, ce n'est plus tout à fait anonyme, mais cela fonctionnera.

<?php 
class Object { 
    function __construct( ) { 
        $n = func_num_args( ) ; 
        for ( $i = 0 ; $i < $n ; $i += 2 ) { 
            $this->{func_get_arg($i)} = func_get_arg($i + 1) ; 
        } 
    } 
} 

$o = new Object( 
    'aProperty', 'value', 
    'anotherProperty', array('element 1', 'element 2')) ; 
echo $o->anotherProperty[1];
?>

Cela produira l' élément 2 . Cela a été volé à un commentaire sur PHP: Classes and Objects .

kba
la source
3

La prise en charge des classes anonymes est disponible depuis PHP 7.0 et est l'analogue le plus proche de l'exemple JavaScript fourni dans la question.

<?php
$object = new class {
    var $p = "value";
    var $p1 = ["john", "johnny"];
};

echo $object->p1[1];

La déclaration de visibilité sur les propriétés ne peut pas être omise (je viens de l'utiliser varcar elle est plus courte que public).

Comme JavaScript, vous pouvez également définir des méthodes pour la classe:

<?php
$object = new class {
    var $p = "value";
    var $p1 = ["john", "johnny"];
    function foo() {return $this->p;}
};

echo $object->foo();
miken32
la source
1

De la documentation PHP, quelques autres exemples:

<?php

$obj1 = new \stdClass; // Instantiate stdClass object
$obj2 = new class{}; // Instantiate anonymous class
$obj3 = (object)[]; // Cast empty array to object

var_dump($obj1); // object(stdClass)#1 (0) {}
var_dump($obj2); // object(class@anonymous)#2 (0) {}
var_dump($obj3); // object(stdClass)#3 (0) {}

?>

$ obj1 et $ obj3 sont du même type, mais $ obj1! == $ obj3. De plus, tous les trois json_encode () en un simple objet JS {}:

<?php

echo json_encode([
    new \stdClass,
    new class{},
    (object)[],
]);

?>

Les sorties:

[{},{},{}]

https://www.php.net/manual/en/language.types.object.php

Ivan Ivković
la source
0

Si vous souhaitez créer un objet (comme en javascript) avec des propriétés dynamiques, sans recevoir d'avertissement de propriété indéfinie, lorsque vous n'avez pas défini de valeur sur propriété

class stdClass {

public function __construct(array $arguments = array()) {
    if (!empty($arguments)) {
        foreach ($arguments as $property => $argument) {
            if(is_numeric($property)):
                $this->{$argument} = null;
            else:
                $this->{$property} = $argument;
            endif;
        }
    }
}

public function __call($method, $arguments) {
    $arguments = array_merge(array("stdObject" => $this), $arguments); // Note: method argument 0 will always referred to the main class ($this).
    if (isset($this->{$method}) && is_callable($this->{$method})) {
        return call_user_func_array($this->{$method}, $arguments);
    } else {
        throw new Exception("Fatal error: Call to undefined method stdObject::{$method}()");
    }
}

public function __get($name){
    if(property_exists($this, $name)):
        return $this->{$name};
    else:
        return $this->{$name} = null;
    endif;
}

public function __set($name, $value) {
    $this->{$name} = $value;
}

}

$obj1 = new stdClass(['property1','property2'=>'value']); //assign default property
echo $obj1->property1;//null
echo $obj1->property2;//value

$obj2 = new stdClass();//without properties set
echo $obj2->property1;//null
Fredtma
la source
0

Cette même technique peut-elle être appliquée en cas de PHP?

Non - car javascript utilise des prototypes / déclaration directe d'objets - en PHP (et dans de nombreux autres langages OO), un objet ne peut être créé qu'à partir d'une classe.

La question devient donc - pouvez-vous créer une classe anonyme.

Encore une fois, la réponse est non - comment instancieriez-vous la classe sans pouvoir la référencer?

symcbean
la source
Vous n'avez pas besoin d'un nom pour créer une instance d'une classe anonyme. Java: Object var = new Object() { ... };- C ++:class { ... } var;
TheOperator
1
Vous pouvez maintenant créer des classes anonymes en PHP.
Victor le
0

Pour celui qui veut un objet récursif:

$o = (object) array(
    'foo' => (object) array(
        'sub' => '...'
    )
);

echo $o->foo->sub;
Jonatas Walker
la source
0

Anoynmus objet wiki


$object=new class (){


};
dılo sürücü
la source