Creazione di oggetti anonimi in php


141

Come sappiamo, la creazione di oggetti anonimi in JavaScript è semplice, come il codice seguente:

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

alert(object.p1[1]);

Produzione:

an alert is raised with value "johnny"

Questa stessa tecnica può essere applicata in PHP? Possiamo creare oggetti anonimi in PHP?


1
Nota: questa è una vecchia domanda, quindi la risposta accettata non è aggiornata. Questa funzione richiesta è stata ora aggiunta a PHP 7. Vedi la risposta di seguito da @ Rizier123.
Simba

@Simba - Grazie per averlo segnalato. Vuoi pubblicare una risposta su StackOverflow qui in questa pagina per aiutare i futuri visitatori?
Sujit Agarwal,

1
Non ho bisogno di; c'è già una risposta con queste informazioni (vedi sotto, di @ Rizier123).
Simba,

Risposte:


40

Sono passati alcuni anni, ma penso di dover aggiornare le informazioni!

Da PHP 7 è stato possibile creare classi anonime, quindi puoi fare cose come questa:

<?php

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

    var_dump($child instanceof Foo); // true

?>

Puoi leggere di più al riguardo nel manuale

Ma non so quanto sia simile a JavaScript, quindi potrebbero esserci alcune differenze tra classi anonime in JavaScript e PHP.


@risyasin Grazie, ho aggiornato la risposta e inserito il link manuale.
Rizier123,

Contrassegnare la risposta come corretta per tenere il passo con le ultime modifiche in php7. Grazie @ Rizier123
Sujit Agarwal

3
Questo è interessante, ma in realtà non affronta la domanda, poiché l'OP stava chiedendo un modo conveniente per inizializzare un oggetto con vari membri senza creare una classe. Non sono sicuro se le classi anonime in php possano essere utilizzate per farlo, e se è possibile, non hai spiegato come.
am15,

228

"Anonimo" non è la terminologia corretta quando si parla di oggetti. Sarebbe meglio dire "oggetto di tipo anonimo ", ma questo non si applica a PHP.

Tutti gli oggetti in PHP hanno una classe. La classe "predefinita" è stdClasse puoi crearne degli oggetti in questo modo:

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

Puoi anche sfruttare il cast di un array su un oggetto per una sintassi più comoda:

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

Tuttavia, tieni presente che è probabile che il cast di un array su un oggetto produca risultati "interessanti" per quelle chiavi dell'array che non sono nomi di variabili PHP validi - ad esempio, ecco una mia risposta che mostra cosa succede quando le chiavi iniziano con le cifre.


1
posso spingere anche più array stimati?
Sujit Agarwal,

2
@CodingFreak: Puoi, ma : se l'array contiene sotto-array e vuoi anche quelli come oggetti, dovrai lanciare ognuno per obiettare esplicitamente.
Jon,

21

Sì, è possibile! Utilizzando questa semplice classe di oggetti anonimi PHP . Come funziona:

// 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"

Naturalmente questo oggetto è un'istanza di AnObjclasse, quindi non è proprio anonimo, ma rende possibile definire metodi al volo, come fanno JavaScript.


È possibile utilizzare create_function per emulare la funzione anonima.
Mihailoff,

Penso che volesse solo un modo pulito per inizializzare un oggetto stdClass con alcuni valori. Puoi farlo con il tuo approccio?
am15,

18

Fino a poco tempo fa ho creato oggetti al volo.

$someObj = json_decode("{}");

Poi:

$someObj->someProperty = someValue;

Ma ora vado con:

$someObj = (object)[];

Quindi come prima:

$someObj->someProperty = someValue;

Naturalmente, se conosci già le proprietà e i valori, puoi impostarli all'interno come è stato menzionato:

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

NB: Non so su quali versioni di PHP funziona, quindi dovresti essere consapevole di ciò. Ma penso che il primo approccio (che è anche breve se non ci sono proprietà da impostare alla costruzione) dovrebbe funzionare per tutte le versioni che hanno json_encode / json_decode


1
In che modo è diverso dall'andare $ someObj = new \ stdClass ()?
JamesNZ,

9

Converti array in oggetto (ma questo non è ricorsivo per i figli secondari):

$obj = (object)  ['myProp' => 'myVal'];

7

Se desideri imitare JavaScript, puoi creare una classe Objecte ottenere quindi lo stesso comportamento. Naturalmente questo non è più abbastanza anonimo, ma funzionerà.

<?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];
?>

Ciò produrrà l' elemento 2 . Questo è stato rubato da un commento su PHP: Classes and Objects .


3

Il supporto per le classi anonime è disponibile da PHP 7.0 ed è l'analogo più vicino all'esempio JavaScript fornito nella domanda.

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

echo $object->p1[1];

La dichiarazione di visibilità sulle proprietà non può essere omessa (l'ho usata solo varperché è più corta di public.)

Come JavaScript, puoi anche definire metodi per la classe:

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

echo $object->foo();

1

Dalla documentazione di PHP, alcuni altri esempi:

<?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 e $ obj3 sono dello stesso tipo, ma $ obj1! == $ obj3. Inoltre, tutti e tre saranno json_encode () su un semplice oggetto JS {}:

<?php

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

?>

Uscite:

[{},{},{}]

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


0

Se si desidera creare un oggetto (come in JavaScript) con proprietà dinamiche, senza ricevere un avviso di proprietà non definita, quando non si è impostato un valore su proprietà

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

0

Questa stessa tecnica può essere applicata in caso di PHP?

No - poiché JavaScript utilizza prototipi / dichiarazione diretta di oggetti - in PHP (e in molti altri linguaggi OO) un oggetto può essere creato solo da una classe.

Quindi la domanda diventa: puoi creare una classe anonima.

Ancora una volta la risposta è no: come faresti un'istanza della classe senza poterla fare riferimento?


Non è necessario un nome per creare un'istanza di una classe anonima. Java: Object var = new Object() { ... };- C ++:class { ... } var;
TheOperator,

1
Ora puoi creare classi anonime in PHP.
Victor,

0

Per chi desidera un oggetto ricorsivo:

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

echo $o->foo->sub;

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.