Tạo các đối tượng ẩn danh trong php


141

Như chúng ta biết, việc tạo các đối tượng ẩn danh trong JavaScript rất dễ dàng, như mã dưới đây:

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

alert(object.p1[1]);

Đầu ra:

an alert is raised with value "johnny"

Kỹ thuật tương tự này có thể được áp dụng trong PHP không? Chúng ta có thể tạo các đối tượng ẩn danh trong PHP không?


1
Lưu ý: đây là một câu hỏi cũ, vì vậy câu trả lời được chấp nhận là lỗi thời. Tính năng này đang được yêu cầu hiện đã được thêm vào PHP 7. Xem câu trả lời dưới đây của @ Rizier123.
Simba

@Simba - Cảm ơn bạn đã chỉ ra. Bạn có muốn đăng câu trả lời trên StackOverflow tại đây trên trang này để giúp khách truy cập trong tương lai không?
Sujit Agarwal

1
Tôi không cần phải làm vậy; đã có câu trả lời với thông tin này (xem bên dưới, bởi @ Rizier123).
Simba

Câu trả lời:


40

Đã được một vài năm, nhưng tôi nghĩ rằng tôi cần phải cập nhật thông tin!

Vì PHP 7 đã có thể tạo các lớp ẩn danh, vì vậy bạn có thể làm những việc như thế này:

<?php

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

    var_dump($child instanceof Foo); // true

?>

Bạn có thể đọc thêm về điều này trong hướng dẫn

Nhưng tôi không biết nó được triển khai tương tự như thế nào với JavaScript, vì vậy có thể có một vài khác biệt giữa các lớp ẩn danh trong JavaScript và PHP.


@risyasin Cảm ơn, đã cập nhật câu trả lời và đặt liên kết thủ công trong đó.
Rizier123

Đánh dấu câu trả lời của bạn là chính xác để theo kịp những thay đổi mới nhất trong php7. Cảm ơn @ Rizier123
Sujit Agarwal

3
Điều này rất thú vị nhưng nó không thực sự giải quyết được câu hỏi, vì OP đã hỏi về một cách thuận tiện để khởi tạo một đối tượng với các thành viên khác nhau mà không tạo ra một lớp. Tôi không chắc liệu các lớp ẩn danh trong php có thể được sử dụng để làm điều đó hay không và nếu có thể, bạn đã không giải thích làm thế nào.
amh15

228

"Ẩn danh" không phải là thuật ngữ chính xác khi nói về các đối tượng. Sẽ là tốt hơn để nói "đối tượng của loại ẩn danh ", nhưng điều này không áp dụng cho PHP.

Tất cả các đối tượng trong PHP có một lớp. Lớp "mặc định" là stdClassvà bạn có thể tạo các đối tượng theo cách này:

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

Bạn cũng có thể tận dụng việc truyền một mảng tới một đối tượng để có cú pháp thuận tiện hơn:

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

Tuy nhiên, xin lưu ý rằng việc truyền một mảng cho một đối tượng có khả năng mang lại kết quả "thú vị" cho các khóa mảng không phải là tên biến PHP hợp lệ - ví dụ: đây là câu trả lời của tôi cho thấy điều gì xảy ra khi khóa bắt đầu bằng chữ số.


1
tôi có thể đẩy nhiều mảng có giá trị không?
Sujit Agarwal

2
@CodingFreak: Bạn có thể, nhưng : nếu mảng chứa các mảng con và bạn cũng muốn chúng là các đối tượng, bạn sẽ cần truyền mọi đối tượng một cách rõ ràng.
Jon

21

Vâng, nó là có thể! Sử dụng lớp đối tượng ẩn danh PHP đơn giản này . Làm thế nào nó hoạt động:

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

Tất nhiên đối tượng này là một thể hiện của AnObjlớp, vì vậy nó không thực sự ẩn danh, nhưng nó có thể xác định các phương thức một cách nhanh chóng, giống như JavaScript.


Bạn có thể sử dụng create_function để mô phỏng chức năng ẩn danh.
Mihailoff

Tôi nghĩ rằng anh ta chỉ muốn một cách gọn gàng để khởi tạo một đối tượng stdClass với một số giá trị. Bạn có thể làm điều đó với cách tiếp cận của bạn?
amh15

18

Cho đến gần đây, đây là cách tôi tạo ra các vật thể một cách nhanh chóng.

$someObj = json_decode("{}");

Sau đó:

$someObj->someProperty = someValue;

Nhưng bây giờ tôi đi với:

$someObj = (object)[];

Rồi như trước:

$someObj->someProperty = someValue;

Tất nhiên nếu bạn đã biết các thuộc tính và giá trị bạn có thể đặt chúng bên trong như đã được đề cập:

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

Lưu ý: Tôi không biết phiên bản PHP nào hoạt động trên đó vì vậy bạn sẽ cần lưu ý về điều đó. Nhưng tôi nghĩ cách tiếp cận đầu tiên (cũng ngắn nếu không có thuộc tính nào được đặt khi xây dựng) nên hoạt động cho tất cả các phiên bản có json_encode / json_decode


1
Làm thế nào khác với đi $ someObj = new \ stdClass ()?
JamesNZ

9

Chuyển đổi mảng thành đối tượng (nhưng điều này không được đệ quy thành con con):

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

7

Nếu bạn muốn bắt chước JavaScript, bạn có thể tạo một lớp Objectvà do đó có cùng hành vi. Tất nhiên điều này không còn vô danh nữa, nhưng nó sẽ hoạt động.

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

Điều đó sẽ xuất phần tử 2 . Điều này đã bị đánh cắp từ một bình luận trên PHP: Classes and Object .


3

Hỗ trợ cho các lớp ẩn danh đã có sẵn từ PHP 7.0 và là ví dụ gần nhất với ví dụ JavaScript được cung cấp trong câu hỏi.

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

echo $object->p1[1];

Khai báo khả năng hiển thị trên các thuộc tính không thể được bỏ qua (Tôi chỉ sử dụng varvì nó ngắn hơn public.)

Giống như JavaScript, bạn cũng có thể định nghĩa các phương thức cho lớp:

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

echo $object->foo();

1

Từ tài liệu PHP, một vài ví dụ nữa:

<?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 và $ obj3 là cùng loại, nhưng $ obj1! == $ obj3. Ngoài ra, cả ba sẽ json_encode () thành một đối tượng JS đơn giản {}:

<?php

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

?>

Đầu ra:

[{},{},{}]

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


0

Nếu bạn muốn tạo đối tượng (như trong javascript) bằng các thuộc tính động, mà không nhận được cảnh báo về thuộc tính không xác định, khi bạn chưa đặt giá trị thành thuộc tính

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

Kỹ thuật tương tự này có thể được áp dụng trong trường hợp PHP không?

Không - bởi vì javascript sử dụng nguyên mẫu / khai báo trực tiếp các đối tượng - trong PHP (và nhiều ngôn ngữ OO khác), một đối tượng chỉ có thể được tạo từ một lớp.

Vì vậy, câu hỏi trở thành - bạn có thể tạo một lớp ẩn danh.

Một lần nữa, câu trả lời là không - làm thế nào bạn có thể khởi tạo lớp mà không thể tham khảo nó?


Bạn không cần một cái tên để tạo một thể hiện của một lớp ẩn danh. Java: Object var = new Object() { ... };- C ++:class { ... } var;
TheOperator

1
Bây giờ bạn có thể tạo các lớp ẩn danh trong PHP.
Victor

0

Đối với một người muốn một đối tượng đệ quy:

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

echo $o->foo->sub;

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.