Создание анонимных объектов в php - PullRequest
126 голосов
/ 17 июня 2011

Как мы знаем, создавать анонимные объекты в JavaScript легко, как в коде ниже:

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

Выход:

an alert is raised with value "johnny"

Можно ли применить эту же технику в случае PHP? Можем ли мы создавать анонимные объекты в PHP?

Ответы [ 9 ]

216 голосов
/ 17 июня 2011

«Аноним» не является правильной терминологией, когда речь идет об объектах. Было бы лучше сказать «объект анонимного типа », но это не относится к PHP.

Все объекты в PHP имеют класс. Класс по умолчанию - stdClass, и вы можете создавать его объекты следующим образом:

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

Вы также можете воспользоваться приведением массива к объекту для более удобного синтаксиса:

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

Однако имейте в виду, что приведение массива к объекту может привести к «интересным» результатам для тех ключей массива, которые не являются допустимыми именами переменных PHP - например, здесь мой ответ, что показывает, что происходит, когда клавиши начинаются с цифр.

33 голосов
/ 29 марта 2015

Прошло несколько лет, но я думаю, что мне нужно обновлять информацию!


В php-7 можно создавать анонимные классы, поэтому вы можете делать такие вещи:

<?php

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

    var_dump($child instanceof Foo); // true

?>

Подробнее об этом можно прочитать в RFC (принято): https://wiki.php.net/rfc/anonymous_classes

Но я не знаю, насколько он похож на Javscript, поэтому между анонимными классами в javascript и php могут быть некоторые различия.

Изменить:

Начиная с опубликованных комментариев, здесь есть ссылка на руководство: http://php.net/manual/en/language.oop5.anonymous.php

20 голосов
/ 12 сентября 2012

Да, это возможно!Используя этот простой PHP анонимный объект класс.Как это работает:

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

Конечно, этот объект является экземпляром класса AnObj, поэтому он на самом деле не анонимный, но позволяет определять методы на лету, как это делает JavaScript.

15 голосов
/ 30 ноября 2016

До недавнего времени я создавал объекты на лету.

$someObj = json_decode("{}");

Тогда:

$someObj->someProperty = someValue;

Но теперь я иду с:

$someObj = (object)[];

Тогда как раньше:

$someObj->someProperty = someValue;

Конечно, если вы уже знаете свойства и значения, вы можете установить их внутри, как уже упоминалось:

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

NB. Я не знаю, с какими версиями PHP это работает, поэтому вам следует помнить об этом. Но я думаю, что первый подход (который также является коротким, если нет свойств для установки в конструкции) должен работать для всех версий, которые имеют json_encode / json_decode

7 голосов
/ 17 июня 2011

Если вы хотите имитировать JavaScript, вы можете создать класс Object и, таким образом, получить то же поведение.Конечно, это уже не совсем анонимно, но это будет работать.

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

Это выдаст элемент 2 .Это было украдено из комментария к PHP: классы и объекты .

6 голосов
/ 18 апреля 2018

Преобразовать массив в объект:

$obj = (object)  ['myProp' => 'myVal'];
0 голосов
/ 05 июня 2018

Для того, кто хочет рекурсивный объект:

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

echo $o->foo->sub;
0 голосов
/ 26 ноября 2015

Если вы хотите создать объект (как в javascript) с динамическими свойствами, без получения предупреждения о неопределенном свойстве, когда вы не установили значение для свойства

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 голосов
/ 17 июня 2011

Может ли этот же метод быть применен в случае PHP?

Нет - поскольку javascript использует прототипы / прямое объявление объектов - в PHP (и многих других языках OO) объект можетсоздается только из класса.

Таким образом, возникает вопрос - можете ли вы создать анонимный класс.

Опять же, ответ - нет - как бы вы создали экземпляр класса, не имея возможности ссылаться на него?

...