Criando objetos anônimos em php


141

Como sabemos, é fácil criar objetos anônimos em JavaScript, como no código abaixo:

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

alert(object.p1[1]);

Resultado:

an alert is raised with value "johnny"

Essa mesma técnica pode ser aplicada em PHP? Podemos criar objetos anônimos em PHP?


1
Nota: esta é uma pergunta antiga, portanto a resposta aceita está desatualizada. Esse recurso solicitado agora foi adicionado ao PHP 7. Veja a resposta abaixo por @ Rizier123.
Simba

@ Simba - Obrigado por apontar. Deseja postar uma resposta no StackOverflow aqui nesta página para ajudar futuros visitantes?
Sujit Agarwal

1
Eu não preciso; já existe uma resposta com essas informações (veja abaixo, por @ Rizier123).
Simba

Respostas:


40

Já faz alguns anos, mas acho que preciso manter as informações atualizadas!

Desde o PHP 7, é possível criar classes anônimas, para que você possa fazer coisas assim:

<?php

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

    var_dump($child instanceof Foo); // true

?>

Você pode ler mais sobre isso no manual

Mas eu não sei o quão semelhante ele é implementado em JavaScript, portanto, pode haver algumas diferenças entre classes anônimas em JavaScript e PHP.


@risyasin Obrigado, atualizou a resposta e colocou o link manual.
Rizier123

Marcar sua resposta como correta para acompanhar as alterações mais recentes no php7. Obrigado @ Rizier123
Sujit Agarwal

3
Isso é interessante, mas realmente não aborda a questão, pois o OP estava perguntando sobre uma maneira conveniente de inicializar um objeto com vários membros sem criar uma classe. Não tenho certeza se classes anônimas em php podem ser usadas para fazer isso e, se puder, você não explicou como.
Amh15

228

"Anônimo" não é a terminologia correta quando se fala de objetos. Seria melhor dizer "objeto do tipo anônimo ", mas isso não se aplica ao PHP.

Todos os objetos no PHP têm uma classe. A classe "padrão" é stdClasse você pode criar objetos dessa maneira:

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

Você também pode tirar vantagem de converter uma matriz em um objeto para obter uma sintaxe mais conveniente:

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

No entanto, esteja ciente de que a conversão de uma matriz para um objeto provavelmente produzirá resultados "interessantes" para aquelas chaves de matriz que não são nomes de variáveis ​​PHP válidos - por exemplo, aqui está uma resposta minha que mostra o que acontece quando as chaves começam com dígitos.


1
posso empurrar vários array com valor também?
precisa

2
@CodingFreak: Você pode, mas : se a matriz contiver sub-matrizes e você também as desejar como objetos, será necessário converter cada objeto explicitamente.
Jon

21

Sim, é possível! Usando este simples classe PHP Anonymous Object . Como 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"

É claro que esse objeto é uma instância da AnObjclasse, portanto não é realmente anônimo, mas possibilita definir métodos rapidamente, como o JavaScript.


Você pode usar create_function para emular uma função anônima.
Mihailoff 26/09

Eu acho que ele só queria uma maneira elegante de inicializar um objeto stdClass com alguns valores. Você pode fazer isso com sua abordagem?
Amh15

18

Até recentemente, foi assim que criei objetos em tempo real.

$someObj = json_decode("{}");

Então:

$someObj->someProperty = someValue;

Mas agora eu vou com:

$someObj = (object)[];

Então, como antes:

$someObj->someProperty = someValue;

Obviamente, se você já conhece as propriedades e os valores, pode configurá-los como foi mencionado:

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

NB: Eu não sei em quais versões do PHP isso funciona, então você precisa estar atento a isso. Mas acho que a primeira abordagem (que também é curta se não houver propriedades para definir em construção) deve funcionar para todas as versões que possuem json_encode / json_decode


1
Qual é a diferença de $ someObj = new \ stdClass ()?
precisa saber é

9

Converta a matriz em objeto (mas isso não é recursivo para sub-filhos):

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

7

Se você deseja imitar o JavaScript, pode criar uma classe Objecte, assim, obter o mesmo comportamento. Claro que isso não é mais completamente anônimo, mas 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];
?>

Isso produzirá o elemento 2 . Isso foi roubado de um comentário no PHP: Classes and Objects .


3

O suporte para classes anônimas está disponível desde o PHP 7.0 e é o análogo mais próximo do exemplo de JavaScript fornecido na pergunta.

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

echo $object->p1[1];

A declaração de visibilidade nas propriedades não pode ser omitida (usei apenas varporque é menor que public.)

Como o JavaScript, você também pode definir métodos para a classe:

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

echo $object->foo();

1

Na documentação do PHP, mais alguns exemplos:

<?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 são do mesmo tipo, mas $ obj1! == $ obj3. Além disso, todos os três json_encode () em um objeto JS simples {}:

<?php

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

?>

Saídas:

[{},{},{}]

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


0

Se você deseja criar um objeto (como em javascript) com propriedades dinâmicas, sem receber um aviso de propriedade indefinida, quando não tiver definido um valor para property

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

Essa mesma técnica pode ser aplicada no caso de PHP?

Não - porque o javascript usa protótipos / declaração direta de objetos - no PHP (e em muitas outras linguagens OO), um objeto só pode ser criado a partir de uma classe.

Então a pergunta se torna - você pode criar uma classe anônima.

Novamente, a resposta é não - como você instanciaria a classe sem poder fazer referência a ela?


Você não precisa de um nome para criar uma instância de uma classe anônima. Java: Object var = new Object() { ... };- C ++:class { ... } var;
TheOperator

1
Você pode criar classes anônimas no PHP agora.
Victor Victor

0

Para quem quer um objeto recursivo:

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

echo $o->foo->sub;

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.