Створення анонімних об'єктів у php


141

Як ми знаємо, створювати анонімні об’єкти в JavaScript легко, як і код нижче:

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

alert(object.p1[1]);

Вихід:

an alert is raised with value "johnny"

Чи можна цю саму техніку застосувати в PHP? Чи можемо ми створити анонімні об’єкти в PHP?


1
Примітка. Це старе питання, тому прийнята відповідь застаріла. Ця функція, про яку вимагають, тепер додана до PHP 7. Дивіться відповідь нижче від @ Rizier123.
Сімба

@Simba - Дякуємо, що вказали на це. Чи бажаєте ви опублікувати відповідь на StackOverflow тут, на цій сторінці, щоб допомогти майбутнім відвідувачам?
Sujit Agarwal

1
Мені не потрібно; вже є відповідь з цією інформацією (див. нижче, від @ Rizier123).
Сімба

Відповіді:


40

Минуло кілька років, але я думаю, що мені потрібно постійно оновлювати інформацію!

З PHP 7 можна було створити анонімні класи, тож ви можете робити такі дії:

<?php

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

    var_dump($child instanceof Foo); // true

?>

Детальніше про це ви можете прочитати в посібнику

Але я не знаю, наскільки вона реалізована в JavaScript, тому може бути кілька відмінностей між анонімними класами в JavaScript та PHP.


@risyasin Спасибі, оновив відповідь і поклав на неї посилання вручну.
Rizier123

Позначте свою відповідь правильною, щоб не відставати від останніх змін у php7. Дякую @ Rizier123
Sujit Agarwal

3
Це цікаво, але насправді це не вирішує питання, оскільки ОП запитував про зручний спосіб ініціалізації об'єкта з різними членами без створення класу. Я не впевнений, чи можна використовувати для цього анонімні класи в php, і якщо це можливо, ви не пояснили, як.
amh15

228

"Анонім" не є правильною термінологією, коли йдеться про об'єкти. Краще було б сказати «об’єкт анонімного типу », але це не стосується PHP.

Усі об'єкти в PHP мають клас. Клас "за замовчуванням" є stdClass, і ви можете створювати його об'єкти таким чином:

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

Ви також можете скористатися передаванням масиву на об'єкт для більш зручного синтаксису:

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

Однак майте на увазі, що передача масиву на об’єкт, ймовірно, дасть "цікаві" результати для тих ключів масиву, які не мають дійсних імен змінних PHP - наприклад, ось моя відповідь, яка показує, що відбувається, коли ключі починаються з цифр.


1
Чи можу я також натиснути безліч значущих масивів?
Sujit Agarwal

2
@CodingFreak: Ви можете, але : якщо масив містить підмасиви, а ви також хочете, щоб вони були як об'єкти, вам потрібно буде передати кожен об'єкт явно.
Джон

21

Так, це можливо! Використання цього простого класу PHP Anonymous Object . Як це працює:

// 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 do.


Ви можете використовувати create_function для емуляції анонімної функції.
Mihailoff

Я думаю, що він просто хотів охайний спосіб ініціалізувати об'єкт stdClass з деякими значеннями. Чи можете ви це зробити зі своїм підходом?
amh15

18

До недавнього часу саме так я створював об’єкти на льоту.

$someObj = json_decode("{}");

Тоді:

$someObj->someProperty = someValue;

Але зараз я йду з:

$someObj = (object)[];

Тоді як раніше:

$someObj->someProperty = someValue;

Звичайно, якщо ви вже знаєте властивості та значення, ви можете встановити їх всередині, як було зазначено:

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

NB: Я не знаю, на яких версіях PHP це працює, тому вам потрібно пам’ятати про це. Але я вважаю, що перший підхід (який також є коротким, якщо у будівництві немає властивостей встановити) повинен працювати для всіх версій, які мають json_encode / json_decode


1
Чим це відрізняється від переходу $ someObj = new \ stdClass ()?
JamesNZ

9

Перетворити масив в об’єкт (але це не рекурсивно для піддітей):

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

7

Якщо ви хочете імітувати 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: Класи та об'єкти .


3

Підтримка анонімних класів доступна з PHP 7.0 і є найближчим аналогом прикладу JavaScript, наведеному у запитанні.

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

echo $object->p1[1];

Декларацію видимості для властивостей не можна опустити (я просто використав, varтому що вона коротша, ніж public.)

Як і JavaScript, ви також можете визначити методи для класу:

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

echo $object->foo();

1

З документації 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(class@anonymous)#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


0

Якщо ви хочете створити об'єкт (наприклад, у 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

Чи можна застосувати цю саму методику у випадку PHP?

Ні - оскільки javascript використовує прототипи / пряме декларування об'єктів - у PHP (та багатьох інших мовах ОО) об’єкт може бути створений лише з класу.

Тож стає питання - чи можна створити анонімний клас.

Знову відповідь - ні - як би ви заповнили клас, не маючи на це посилання?


Вам не потрібно імені для створення примірника анонімного класу. Java: Object var = new Object() { ... };- C ++:class { ... } var;
Оператор

1
Ви можете створити анонімні класи в PHP зараз.
Віктор


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.