2011-06-17 18 views
101

Como sabemos, la creación de objetos anónimos en JavaScript es fácil, al igual que el código de abajo:Creación de objetos anónimos en php

var object = { 
    p : "value", 
    p1 : [ "john", "johnny" ] } ; 
alert(object.p1[1]) ; 

Salida:

an alert is raised with value "johnny" 

Puede esta misma técnica se aplica en el caso de PHP? ¿Podemos crear objetos anónimos en PHP?

+1

Nota: esta es una pregunta antigua, por lo que la respuesta aceptada es -fecha. Esta función solicitada ahora se ha agregado a PHP 7. Consulte la respuesta a continuación por @Rizier123. – Simba

+0

@Simba - Gracias por señalarlo. ¿Le gustaría publicar una respuesta en StackOverflow aquí en esta página para ayudar a los futuros visitantes? –

+1

No es necesario; ya hay una respuesta con esta información (ver más abajo, por @ Rizier123). – Simba

Respuesta

29

¡Han pasado algunos años, pero creo que necesito mantener la información actualizada!


en PHP-7 es posible crear clases anónimas, lo que es capaz de hacer cosas como esta:

<?php 

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

    var_dump($child instanceof Foo); // true 

?> 

Puede leer más sobre esto en el RFC (Se es aceptado): https://wiki.php.net/rfc/anonymous_classes

Pero no sé qué tan similar se implementa con Javscript, por lo que puede haber algunas diferencias entre las clases anónimas en javascript y php.

Editar:

A partir de los comentarios publicados, aquí está el enlace al manual ahora: http://php.net/manual/en/language.oop5.anonymous.php

+0

Gracias por compartir esta información :) –

+0

URL de documentación actualizada: http://php.net/manual/en/language.oop5.anonymous.php – risyasin

+0

@risyasin Gracias, actualizó la respuesta y puso el enlace manual en ella. – Rizier123

191

"Anónimo" no es la terminología correcta cuando se habla de objetos. Sería mejor decir "objeto de anónimo tipo", pero esto no se aplica a PHP.

Todos los objetos en PHP tienen una clase. La clase "default" es stdClass, y se pueden crear objetos de esta manera:

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

También puede tomar ventaja de casting an array to an object de una sintaxis más conveniente:

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

Sin embargo, tenga en cuenta que lanzar una matriz a un objeto es probable que arroje resultados "interesantes" para esas claves de matriz que no son nombres de variable de PHP válidos; por ejemplo, here's una respuesta mía que muestra lo que sucede cuando las claves comienzan con dígitos.

+1

¿Puedo empujar una matriz de valores múltiples también? –

+1

@CodingFreak: puede, ** pero **: si la matriz contiene sub-arrays y usted también los quiere como objetos, tendrá que convertir cada uno a un objeto explícitamente. – Jon

+5

Lo siento por el fuera de tema. Pero cada vez que leo "resultados" interesantes "cuando leo sobre PHP, comienzo a sentir miedo verdadero dentro de mí. – Areks

6

Si desea imitar a JavaScript, puede crear una clase Object, y así obtener el mismo comportamiento. Por supuesto, esto ya no es bastante anónimo, pero funcionará.

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

Esa es la salida elemento 2. Esto fue robado del a comment on PHP: Classes and Objects.

2

¿Se puede aplicar esta misma técnica en el caso de PHP?

No, porque javascript usa prototipos/declaración directa de objetos: en PHP (y en muchos otros lenguajes de OO), un objeto solo se puede crear a partir de una clase.

Entonces la pregunta es: ¿puede crear una clase anónima?

Nuevamente, la respuesta es no, ¿cómo crearías una instancia de la clase sin poder hacer referencia a ella?

+0

No necesita un nombre para crear una instancia de una clase anónima. Java: 'Object var = new Object() {...};' - C++: 'clase {...} var;' – TheOperator

18

Sí, ¡es posible! Usando esta simple clase PHP Anonymous Object. Cómo funciona:

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

Por supuesto, este objeto es una instancia de la clase AnObj, por lo que no es realmente anónimo, sino que hace posible definir métodos sobre la marcha, como JavaScript hacer.

+0

No funciona por debajo de 5.3 – Pacerier

+0

Puede usar [create_function] (http://php.net/manual/en/function.create-function.php) para emular la función anónima. – Mihailoff

0

Si desea crear el objeto (como en javascript) con propiedades dinámicas, sin recibir una advertencia de propiedad indefinida, cuando no ha establecido un valor para la propiedad

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 
8

Hasta hace poco, así es como creé objetos sobre la marcha.

$someObj = json_decode("{}"); 

continuación:

$someObj->someProperty = someValue; 

Pero ahora voy con:

$someObj = (object)[]; 

Entonces como antes:

$someObj->someProperty = someValue; 

Por supuesto, si usted ya conoce las propiedades y valores puedes ponerlos dentro como se ha mencionado:

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

NB: No sé en qué versiones de PHP esto funciona así que tendrías que ser consciente de eso. Pero creo que el primer enfoque (que también es corto si no hay propiedades para establecer en la construcción) debería funcionar para todas las versiones que tengan json_encode/json_decode

+0

¿Cómo es eso diferente de ir $ someObj = new \ stdClass()? – JamesNZ