Создание анонимных объектов в php
Как известно, создание анонимных объектов в JavaScript легко, например, код ниже:
var object = {
p : "value",
p1 : [ "john", "johnny" ] } ;
alert(object.p1[1]) ;
Вывод:
an alert is raised with value "johnny"
Можно ли применить эту же методику в случае PHP? Можем ли мы создать анонимные объекты в PHP?
Ответы
Ответ 1
Прошло несколько лет, но я думаю, что мне нужно обновлять информацию!
В 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.
Edit:
Как и в опубликованных комментариях, вот ссылка на руководство: http://php.net/manual/en/language.oop5.anonymous.php
Ответ 2
"Анонимный" не является правильной терминологией при обсуждении объектов. Лучше сказать "объект анонимного типа", но это не относится к PHP.
Все объекты в PHP имеют класс. Класс по умолчанию stdClass
, и вы можете создавать его объекты следующим образом:
$obj = new stdClass;
$obj->aProperty = 'value';
Вы также можете использовать листинг массива для объекта для более удобного синтаксиса:
$obj = (object)array('aProperty' => 'value');
print_r($obj);
Однако следует иметь в виду, что приведение массива к объекту может привести к "интересным" результатам для тех ключей массива, которые не являются допустимыми именами переменных PHP, например здесь мой ответ, который показывает, что происходит, когда ключи начинаются с цифр.
Ответ 3
Да, это возможно! Используя этот простой класс Анонимный объект 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.
Ответ 4
До недавнего времени именно так я создал объекты на лету.
$someObj = json_decode("{}");
Тогда:
$someObj->someProperty = someValue;
Но теперь я иду:
$someObj = (object)[];
Затем, как и раньше:
$someObj->someProperty = someValue;
Конечно, если вы уже знаете свойства и значения, вы можете установить их внутри, как было упомянуто:
$someObj = (object)['prop1' => 'value1','prop2' => 'value2'];
NB: Я не знаю, на каких версиях PHP это работает, поэтому вам нужно помнить об этом. Но я думаю, что первый подход (который также является коротким, если нет свойств для построения при построении) должен работать для всех версий с json_encode/json_decode
Ответ 5
Если вы хотите подражать 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
Преобразовать массив в объект:
$obj = (object) ['myProp' => 'myVal'];
Ответ 7
Можно ли применить эту же методику в случае PHP?
Нет - поскольку javascript использует прототипы/прямое объявление объектов - в PHP (и во многих других языках OO) объект может быть создан только из класса.
Итак, возникает вопрос - можете ли вы создать анонимный класс.
Опять ответ: нет - как бы вы создавали экземпляр класса, не имея возможности ссылаться на него?
Ответ 8
Если вы хотите создать объект (например, в javascript) с динамическими свойствами, не получая предупреждение о свойстве undefined, если вы не установили значение свойства
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
Ответ 9
Для того, кто хочет рекурсивный объект:
$o = (object) array(
'foo' => (object) array(
'sub' => '...'
)
);
echo $o->foo->sub;
Ответ 10
Из документации PHP еще несколько примеров:
<?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([email protected])#2 (0) {}
var_dump($obj3); // object(stdClass)#3 (0) {}
?>
$ obj1 и $ obj3 имеют одинаковый тип, но $ obj1! == $ obj3. Кроме того, все три будут json_encode() в простой объект JS {}:
<?php
echo json_encode([
new \stdClass,
new class{},
(object)[],
]);
?>
Выходы:
[{},{},{}]
https://www.php.net/manual/en/language.types.object.php