การสร้างวัตถุที่ไม่ระบุชื่อใน 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
สิ่งนี้น่าสนใจ แต่ไม่ได้ตอบคำถามอย่างแท้จริงเนื่องจาก OP ได้ถามถึงวิธีที่สะดวกในการเริ่มต้นวัตถุกับสมาชิกหลาย ๆ คนโดยไม่ต้องสร้างชั้นเรียน ฉันไม่แน่ใจว่าคลาสนิรนามใน php สามารถใช้ทำสิ่งนั้นได้หรือไม่และถ้าทำได้คุณไม่ได้อธิบายว่าจะทำอย่างไร
amh15

228

"Anonymous" ไม่ใช่คำศัพท์ที่ถูกต้องเมื่อพูดถึงวัตถุ มันจะเป็นการดีกว่าถ้าจะพูดว่า "object of anonymous type " แต่สิ่งนี้ไม่สามารถใช้ได้กับ PHP

วัตถุทั้งหมดใน PHP มีคลาส คลาส "default" คือstdClassและคุณสามารถสร้างวัตถุได้ด้วยวิธีนี้:

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

คุณยังสามารถใช้ประโยชน์จากการคัดเลือกอาเรย์ไปยังวัตถุสำหรับไวยากรณ์ที่สะดวกมากขึ้น:

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

อย่างไรก็ตามโปรดทราบว่าการคัดเลือกอาเรย์กับวัตถุนั้นน่าจะให้ผลลัพธ์ที่ "น่าสนใจ" สำหรับคีย์อาเรย์เหล่านั้นที่ไม่ใช่ชื่อตัวแปร PHP ที่ถูกต้องตัวอย่างเช่นนี่คือคำตอบของฉันที่แสดงสิ่งที่เกิดขึ้นเมื่อคีย์เริ่มต้นด้วยตัวเลข


1
ฉันสามารถผลักดันอาเรย์ที่มีค่าหลายอันได้ด้วยหรือไม่
Sujit Agarwal

2
@CodingFreak: คุณสามารถทำได้แต่ : ถ้าอาร์เรย์มีอาร์เรย์ย่อยและคุณต้องการให้มันเป็นวัตถุเช่นกันคุณจะต้องส่งทุก ๆ ออบเจ็กต์ออกมาอย่างชัดเจน
Jon

21

ใช่มันเป็นไปได้! การใช้คลาสวัตถุ 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 ทำ


คุณสามารถใช้create_functionเพื่อเลียนแบบฟังก์ชั่นที่ไม่ระบุชื่อ
Mihailoff

ฉันคิดว่าเขาต้องการวิธีที่เป็นระเบียบในการเริ่มต้นวัตถุ stdClass ด้วยค่าบางอย่าง คุณสามารถทำสิ่งนั้นกับแนวทางของคุณได้หรือไม่?
amh15

18

จนกระทั่งเมื่อเร็ว ๆ นี้นี่คือวิธีที่ฉันสร้างวัตถุได้ทันที

$someObj = json_decode("{}");

แล้ว:

$someObj->someProperty = someValue;

แต่ตอนนี้ฉันไปกับ:

$someObj = (object)[];

เหมือนก่อนหน้านี้:

$someObj->someProperty = someValue;

แน่นอนถ้าคุณรู้คุณสมบัติและค่าต่าง ๆ แล้วคุณสามารถตั้งค่าไว้ภายในดังที่ได้กล่าวไว้:

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

หมายเหตุ: ฉันไม่ทราบว่าเวอร์ชันของ PHP นี้ใช้งานได้ดังนั้นคุณจะต้องระวัง แต่ฉันคิดว่าวิธีแรก (ซึ่งสั้นหากไม่มีคุณสมบัติที่จะสร้าง) ควรทำงานสำหรับทุกรุ่นที่มี json_encode / json_decode


1
มันแตกต่างจากการไป $ someObj = new \ stdClass () อย่างไร
JamesNZ

9

แปลงอาร์เรย์เป็นวัตถุ (แต่นี่ไม่ใช่แบบเรียกซ้ำเพื่อ sub-childs):

$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

หากคุณต้องการสร้างวัตถุ (เช่นในจาวาสคริปต์) ด้วยคุณสมบัติแบบไดนามิกโดยไม่ได้รับคำเตือนเกี่ยวกับคุณสมบัติที่ไม่ได้กำหนดเมื่อคุณไม่ได้ตั้งค่าให้กับคุณสมบัติ

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 ได้หรือไม่?

ไม่ - เพราะจาวาสคริปต์ใช้ต้นแบบ / การประกาศวัตถุโดยตรง - ใน PHP (และภาษา OO อื่น ๆ ) วัตถุสามารถสร้างได้จากชั้นเรียนเท่านั้น

ดังนั้นคำถามจะกลายเป็น - คุณสามารถสร้างคลาสที่ไม่ระบุชื่อได้หรือไม่

คำตอบคือไม่ - คุณจะยกตัวอย่างคลาสได้อย่างไรโดยไม่สามารถอ้างอิงได้


คุณไม่ต้องการชื่อเพื่อสร้างอินสแตนซ์ของคลาสที่ไม่ระบุชื่อ Java: Object var = new Object() { ... };- C ++:class { ... } var;
TheOperator

1
คุณสามารถสร้างคลาสที่ไม่ระบุชื่อใน PHP ได้ทันที
Victor

0

สำหรับผู้ที่ต้องการวัตถุแบบเรียกซ้ำ:

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

echo $o->foo->sub;

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.