แปลงวัตถุ PHP เป็นอาเรย์แบบเชื่อมโยง


760

ฉันรวม API กับเว็บไซต์ของฉันซึ่งทำงานกับข้อมูลที่เก็บไว้ในวัตถุในขณะที่ฉันเขียนโค้ดโดยใช้อาร์เรย์

ฉันต้องการฟังก์ชั่นที่รวดเร็วและสกปรกในการแปลงวัตถุเป็นอาร์เรย์

คำตอบ:


1392

เพียงพิมพ์มัน

$array = (array) $yourObject;

จากอาร์เรย์ :

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

ตัวอย่าง: วัตถุอย่างง่าย

$object = new StdClass;
$object->foo = 1;
$object->bar = 2;

var_dump( (array) $object );

เอาท์พุท:

array(2) {
  'foo' => int(1)
  'bar' => int(2)
}

ตัวอย่าง: วัตถุที่ซับซ้อน

class Foo
{
    private $foo;
    protected $bar;
    public $baz;

    public function __construct()
    {
        $this->foo = 1;
        $this->bar = 2;
        $this->baz = new StdClass;
    }
}

var_dump( (array) new Foo );

เอาท์พุท (พร้อม \ 0s แก้ไขเพื่อความชัดเจน):

array(3) {
  '\0Foo\0foo' => int(1)
  '\0*\0bar' => int(2)
  'baz' => class stdClass#2 (0) {}
}

ผลลัพธ์ด้วยvar_exportแทนที่จะเป็นvar_dump:

array (
  '' . "\0" . 'Foo' . "\0" . 'foo' => 1,
  '' . "\0" . '*' . "\0" . 'bar' => 2,
  'baz' =>
  stdClass::__set_state(array(
  )),
)

การแสดงภาพด้วยวิธีนี้จะไม่ทำให้กราฟวัตถุลึกลงไปและคุณจำเป็นต้องใช้ไบต์ว่าง (ดังที่อธิบายไว้ในใบเสนอราคาด้วยตนเอง) เพื่อเข้าถึงแอตทริบิวต์ที่ไม่ใช่แบบสาธารณะ ดังนั้นวิธีนี้จะทำงานได้ดีที่สุดเมื่อทำการคัดเลือกวัตถุหรือวัตถุ StdClass ที่มีคุณสมบัติสาธารณะเท่านั้น สำหรับสิ่งที่รวดเร็วและสกปรก (สิ่งที่คุณขอ) มันใช้ได้

ดูโพสต์บล็อกเชิงลึกนี้:


3
พิจารณาArrayAccessอินเทอร์เฟซซึ่งอาจใช้ร่วมกับโซลูชันนี้ php.net/manual/en/class.arrayaccess.php
alttag

3
คุณมีคีย์จำนวนเต็มที่จะแปลงเป็นสตริงและอาจทำให้เกิดปัญหาใหญ่ เช่น[1 => "one"]กลายเป็น["1" => "one"]
Oleg

2
@Howie Typecasting ด้วย(array)และ(object)ทำงานได้อย่างน่าเชื่อถือและเหมือนกันในทุกรุ่นตั้งแต่ PHP 4.3 ดู3v4l.org/X6lhm หากคุณได้รับข้อผิดพลาดทางไวยากรณ์คุณทำผิดพลาด
Gordon

2
@Howie ดูส่วนการเปลี่ยนแปลงสำหรับ emptyคุณไม่สามารถใช้นิพจน์emptyก่อนหน้า 5.5 สิ่งนี้ไม่เกี่ยวข้องกับ typecasting;)
Gordon

4
กำหนด ให้ผู้ ปฏิบัติ งาน กระทำ ใน สิ่ง ชนิดเดียวกันอย่างซ้ำ ๆ ใช่. พิมพ์ Freakin CAST! ดี. +1
Kaushik Makwana

346

คุณสามารถแปลงออบเจกต์ที่อยู่ลึกเข้าไปในอาเรย์แบบเชื่อมโยงได้อย่างรวดเร็วโดยอาศัยพฤติกรรมของฟังก์ชันการเข้ารหัส / ถอดรหัส JSON:

$array = json_decode(json_encode($nested_object), true);

12
นี่เป็นทางออกที่ดีที่สุดหากคุณต้องการการแปลงแบบเรียกซ้ำแบบลึก (และแน่นอนว่าไม่ต้องคำนึงถึงประสิทธิภาพที่ไม่ดี)
Julian Habekost

2
สิ่งนี้ช่วยฉันในสถานการณ์ของฉันโดยสิ้นเชิงขอบคุณมาก
Cesar Bielich

9
ฉันคิดว่ามันยังใช้งานได้ ... อย่าลืมตั้งค่าพารามิเตอร์ที่ 2 เป็นจริง
Kirk B

3
พารามิเตอร์ที่สองแก้ปัญหาทำงานกับ PHP 5.6.25 ขอบคุณ!
Ju Oliveira

3
ทำงานได้สมบูรณ์แบบสำหรับวัตถุที่ซ้อนกัน! ขอบคุณ!
ทำนองเพลง

68

จากการตีครั้งแรกของ Google สำหรับ " PHP object to assoc array " เรามี:

function object_to_array($data)
{
    if (is_array($data) || is_object($data))
    {
        $result = array();
        foreach ($data as $key => $value)
        {
            $result[$key] = object_to_array($value);
        }
        return $result;
    }
    return $data;
}

แหล่งที่มาที่ codesnippets.joyent.com


16
โดยส่วนตัวแล้วฉันไม่ชอบความคิดในการเรียกใช้ฟังก์ชันสำหรับทุกค่า ฉันมีรุ่นที่คล้ายกัน แต่มี 3 บรรทัด: function objectToArray($o) { $a = array(); foreach ($o as $k => $v) $a[$k] = (is_array($v) || is_object($v)) ? objectToArray($v): $v; return $a; }นี่เป็นการตั้งค่าอะไรก็ตามที่ไม่ใช่วัตถุหรืออาร์เรย์และดำเนินการต่อโดยไม่ต้องเรียกใช้ซ้ำตามวิธีเว้นแต่ว่าจำเป็น
SpYk3HH

13
@ SpYk3HH: เขียนคำตอบของคุณเอง?
DanMan

2
การเข้าชมครั้งแรกของ "php object to assoc array" คือstackoverflow.com/questions/4345554/…
Chris

นี่ (และรุ่นจาก @ SpYk3HH) ดูเหมือนว่าจะทำงานได้ช้ากว่าตัวเลือก json_encode ( stackoverflow.com/a/16111687/470749 ) ฉันไม่รู้ว่าทำไมแนวทางเหล่านี้ถึงจะดีกว่า
Ryan

1
@Ryan json การเข้ารหัสและถอดรหัสจะไม่ทำงานกับค่า NaN และ INFINITE สำหรับ float และอาจมีปัญหาอื่น ๆ ที่ฉันไม่สามารถนึกถึงได้จากส่วนบนของหัว แต่สำหรับหลาย ๆ กรณีมันอาจเป็นตัวเลือกที่ดีกว่า ในฐานะที่เป็นสำหรับการเพิ่มประสิทธิภาพสิ่งที่มันต้องการคือบริบท - ให้ฉันเสียบโพสต์ที่ผมเขียนเกี่ยวกับเรื่องนี้evidentlycube.com/blog/game-optimization/when-to-optimize tl; dr, เป็น, อย่าปรับสิ่งที่ไม่ต้องใช้เวลามากในการทำงานเพราะผลประโยชน์ไม่มีความหมายในบริบทของแอปพลิเคชันทั้งหมด
Maurycy

61

หากคุณสมบัติวัตถุของคุณเป็นแบบสาธารณะคุณสามารถทำได้:

$array =  (array) $object;

หากพวกเขาเป็นส่วนตัวหรือได้รับการคุ้มครองพวกเขาจะมีชื่อคีย์แปลก ๆ ในอาร์เรย์ ดังนั้นในกรณีนี้คุณจะต้องใช้ฟังก์ชันต่อไปนี้:

function dismount($object) {
    $reflectionClass = new ReflectionClass(get_class($object));
    $array = array();
    foreach ($reflectionClass->getProperties() as $property) {
        $property->setAccessible(true);
        $array[$property->getName()] = $property->getValue($object);
        $property->setAccessible(false);
    }
    return $array;
}

หากคุณสมบัติของคุณได้รับการปกป้องจะ setAccessible (false) จะเปลี่ยนกลับเป็นทัศนวิสัยที่ป้องกัน หรือมันจะทำให้มันเป็นส่วนตัว?
Nick Mitchell

ทางออกเดียวที่ฉันพบซึ่งทำงานกับคุณสมบัติที่ได้รับการป้องกัน ขอบคุณ
dav

3
ทางออกที่ดีที่สุดสำหรับตัวแปรส่วนตัวและการป้องกัน !!
HIRA THAKUR

ที่นี่บรรทัด $ ทรัพย์สิน -> setAccessible (เท็จ); จะถูกประหารชีวิตในทุก ๆ สถานที่ - แม้ว่าจะเป็นสาธารณะ ...
Francois Bourgeois

ยอดเยี่ยม ... น่าทึ่ง ... สุดยอด ขอบคุณ
Farid Abbas

14
class Test{
    const A = 1;
    public $b = 'two';
    private $c = test::A;

    public function __toArray(){
        return call_user_func('get_object_vars', $this);
    }
}

$my_test = new Test();
var_dump((array)$my_test);
var_dump($my_test->__toArray());

เอาท์พุต

array(2) {
    ["b"]=>
    string(3) "two"
    ["Testc"]=>
    int(1)
}
array(1) {
    ["b"]=>
    string(3) "two"
}

1
ข้อดีและข้อเสียของการแก้ปัญหานี้? คลาสที่ประกาศว่าเป็นคลาสทดสอบ {const A = 1; สาธารณะ $ parent = ทดสอบใหม่ (); }
Matteo Gaggiano

13

นี่คือรหัสบางส่วน:

function object_to_array($data) {
    if ((! is_array($data)) and (! is_object($data)))
        return 'xxx'; // $data;

    $result = array();

    $data = (array) $data;
    foreach ($data as $key => $value) {
        if (is_object($value))
            $value = (array) $value;
        if (is_array($value))
            $result[$key] = object_to_array($value);
        else
            $result[$key] = $value;
    }
    return $result;
}

ทำงานได้ดีที่สุดสำหรับฉัน (แต่ฉันจำเป็นต้องลบ 'xxx' และส่งคืนข้อมูล $)
35790 Gerfried

12

คำตอบอื่น ๆ ทั้งหมดที่โพสต์ที่นี่จะทำงานกับคุณลักษณะสาธารณะเท่านั้น นี่คือโซลูชันหนึ่งที่ทำงานกับวัตถุที่เหมือนJavaBeansโดยใช้การสะท้อนและการกระจาย:

function entity2array($entity, $recursionDepth = 2) {
    $result = array();
    $class = new ReflectionClass(get_class($entity));
    foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
        $methodName = $method->name;
        if (strpos($methodName, "get") === 0 && strlen($methodName) > 3) {
            $propertyName = lcfirst(substr($methodName, 3));
            $value = $method->invoke($entity);

            if (is_object($value)) {
                if ($recursionDepth > 0) {
                    $result[$propertyName] = $this->entity2array($value, $recursionDepth - 1);
                }
                else {
                    $result[$propertyName] = "***";  // Stop recursion
                }
            }
            else {
                $result[$propertyName] = $value;
            }
        }
    }
    return $result;
}

ใช่ แต่ ... ถ้าคุณใช้ Object / Array เป็นตัวแปรซึ่งเป็นสิ่งที่นำไปสู่สิ่งนี้ด้วยทำไมคุณต้องการอะไรนอกเหนือจากpublicคุณสมบัติ
SpYk3HH

@ SpYk3HH: ฉันไม่ได้ถามคำถาม ฉันไม่รู้ด้วยซ้ำว่าทำไมใคร ๆ ถึงชอบอาร์เรย์มากกว่าสิ่งแรก
Francois Bourgeois

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

11

เกี่ยวกับget_object_vars($obj)อะไร ดูเหมือนว่ามีประโยชน์หากคุณต้องการเข้าถึงคุณสมบัติสาธารณะของวัตถุเท่านั้น

ดูget_object_vars


10

พิมพ์ cast วัตถุของคุณไปยังอาร์เรย์

$arr =  (array) $Obj;

มันจะแก้ปัญหาของคุณ.


5
ไม่มันจะไม่ถ้าคุณมีคุณสมบัติส่วนตัวหรือที่ได้รับการป้องกัน
forsberg

2
ทางออกที่ง่ายที่สุด ขอบคุณ
ASD

6

ก่อนอื่นถ้าคุณต้องการอาเรย์จากออบเจ็กต์คุณอาจจะต้องประกอบด้วยข้อมูลเป็นอาเรย์ก่อน ลองคิดดู

อย่าใช้foreachคำสั่งหรือการแปลง JSON หากคุณกำลังวางแผนสิ่งนี้อยู่คุณกำลังทำงานกับโครงสร้างข้อมูลไม่ใช่กับวัตถุ

หากคุณต้องการใช้วิธีการเชิงวัตถุจริงๆเพื่อให้ได้รหัสที่สะอาดและบำรุงรักษาได้ ตัวอย่างเช่น:

วัตถุเป็นอาร์เรย์

class PersonArray implements \ArrayAccess, \IteratorAggregate
{
    public function __construct(Person $person) {
        $this->person = $person;
    }
    // ...
 }

หากคุณต้องการคุณสมบัติทั้งหมดให้ใช้วัตถุการถ่ายโอน:

class PersonTransferObject
{
    private $person;

    public function __construct(Person $person) {
        $this->person = $person;
    }

    public function toArray() {
        return [
            // 'name' => $this->person->getName();
        ];
    }

 }

6

คุณสามารถใช้ฟังก์ชั่นนี้เพื่อรับผลลัพธ์:

function objetToArray($adminBar){
    $reflector = new ReflectionObject($adminBar);
    $nodes = $reflector->getProperties();
    $out = [];
    foreach ($nodes as $node) {
        $nod = $reflector->getProperty($node->getName());
        $nod->setAccessible(true);
        $out[$node->getName()] = $nod->getValue($adminBar);
    }
    return $out;
}

ใช้PHP 5หรือใหม่กว่า


5

นี่คือฟังก์ชั่น PHP แบบเรียกซ้ำเพื่อแปลงวัตถุ PHP เป็นอาเรย์แบบเชื่อมโยง:

// ---------------------------------------------------------
// ----- object_to_array_recursive --- function (PHP) ------
// ---------------------------------------------------------
// --- arg1: -- $object  =  PHP Object         - required --
// --- arg2: -- $assoc   =  TRUE or FALSE      - optional --
// --- arg3: -- $empty   =  '' (Empty String)  - optional --
// ---------------------------------------------------------
// ----- Return: Array from Object --- (associative) -------
// ---------------------------------------------------------

function object_to_array_recursive($object, $assoc=TRUE, $empty='')
{
    $res_arr = array();

    if (!empty($object)) {

        $arrObj = is_object($object) ? get_object_vars($object) : $object;

        $i=0;
        foreach ($arrObj as $key => $val) {
            $akey = ($assoc !== FALSE) ? $key : $i;
            if (is_array($val) || is_object($val)) {
                $res_arr[$akey] = (empty($val)) ? $empty : object_to_array_recursive($val);
            }
            else {
                $res_arr[$akey] = (empty($val)) ? $empty : (string)$val;
            }
            $i++;
        }
    }
    return $res_arr;
}

// ---------------------------------------------------------
// ---------------------------------------------------------

ตัวอย่างการใช้งาน:

// ---- Return associative array from object, ... use:
$new_arr1 = object_to_array_recursive($my_object);
// -- or --
// $new_arr1 = object_to_array_recursive($my_object, TRUE);
// -- or --
// $new_arr1 = object_to_array_recursive($my_object, 1);


// ---- Return numeric array from object, ... use:
$new_arr2 = object_to_array_recursive($my_object, FALSE);

3
.. หรือ oneliner:$new_arr1 = (array) $my_object;
FooBar

1
เวอร์ชัน oneliner นั้นตื้นดังนั้นจึงไม่เทียบเท่า
Jonathan Lidbeck


5

คุณยังสามารถสร้างฟังก์ชั่นใน PHP เพื่อแปลงอาเรย์วัตถุ:

function object_to_array($object) {
    return (array) $object;
}

@ Akintunde-Rotimi ฉันได้สร้างฟังก์ชั่นทั่วไปและแสดงให้เห็น
Rakhi Prajapati

4

คุณอาจต้องการทำสิ่งนี้เมื่อคุณรับข้อมูลเป็นวัตถุจากฐานข้อมูล:

// Suppose 'result' is the end product from some query $query

$result = $mysqli->query($query);
$result = db_result_to_array($result);

function db_result_to_array($result)
{
    $res_array = array();

    for ($count=0; $row = $result->fetch_assoc(); $count++)
        $res_array[$count] = $row;

    return $res_array;
}

2
มีคำตอบที่ยอมรับกับ 41 upvotes ไม่ใช่ 1 หรือ 10, 41. คำตอบของคุณเพิ่มอะไร?
Yaroslav

4

ฟังก์ชั่นที่กำหนดเองเพื่อแปลง stdClass เป็นอาร์เรย์:

function objectToArray($d) {
    if (is_object($d)) {
        // Gets the properties of the given object
        // with get_object_vars function
        $d = get_object_vars($d);
    }

    if (is_array($d)) {
        /*
        * Return array converted to object
        * Using __FUNCTION__ (Magic constant)
        * for recursive call
        */
        return array_map(__FUNCTION__, $d);
    } else {
        // Return array
        return $d;
    }
}

อีกฟังก์ชั่นที่กำหนดเองเพื่อแปลง Array เป็น stdClass:

function arrayToObject($d) {
    if (is_array($d)) {
        /*
        * Return array converted to object
        * Using __FUNCTION__ (Magic constant)
        * for recursive call
        */
        return (object) array_map(__FUNCTION__, $d);
    } else {
        // Return object
        return $d;
    }
}

ตัวอย่างการใช้งาน:

// Create new stdClass Object
$init = new stdClass;

// Add some test data
$init->foo = "Test data";
$init->bar = new stdClass;
$init->bar->baaz = "Testing";
$init->bar->fooz = new stdClass;
$init->bar->fooz->baz = "Testing again";
$init->foox = "Just test";

// Convert array to object and then object back to array
$array = objectToArray($init);
$object = arrayToObject($array);

// Print objects and array
print_r($init);
echo "\n";
print_r($array);
echo "\n";
print_r($object);

4

ใช้:

function readObject($object) {
    $name = get_class ($object);
    $name = str_replace('\\', "\\\\", $name); \\ Outcomment this line, if you don't use
                                              \\ class namespaces approach in your project
    $raw = (array)$object;

    $attributes = array();
    foreach ($raw as $attr => $val) {
        $attributes[preg_replace('('.$name.'|\*|)', '', $attr)] = $val;
    }
    return $attributes;
}

มันจะส่งกลับอาร์เรย์ที่ไม่มีตัวอักษรพิเศษและชื่อชั้น


4

คำตอบนี้เป็นเพียงการรวมกันของคำตอบที่แตกต่างกันของโพสต์นี้ แต่มันเป็นวิธีการแปลงวัตถุ PHP ด้วยคุณสมบัติสาธารณะหรือส่วนตัวที่มีค่าง่ายหรืออาร์เรย์เป็นอาร์เรย์เชื่อมโยง ...

function object_to_array($obj)
{
    if (is_object($obj))
        $obj = (array)$this->dismount($obj);
    if (is_array($obj)) {
        $new = array();
        foreach ($obj as $key => $val) {
            $new[$key] = $this->object_to_array($val);
        }
    }
    else
        $new = $obj;
    return $new;
}

function dismount($object)
{
    $reflectionClass = new \ReflectionClass(get_class($object));
    $array = array();
    foreach ($reflectionClass->getProperties() as $property) {
        $property->setAccessible(true);
        $array[$property->getName()] = $property->getValue($object);
        $property->setAccessible(false);
    }
    return $array;
}

3

การนำไปใช้กับรหัส "well-knwon" บางอย่าง

/*** mixed Obj2Array(mixed Obj)***************************************/ 
static public function Obj2Array($_Obj) {
    if (is_object($_Obj))
        $_Obj = get_object_vars($_Obj);
    return(is_array($_Obj) ? array_map(__METHOD__, $_Obj) : $_Obj);   
} // BW_Conv::Obj2Array

โปรดสังเกตว่าหากฟังก์ชั่นเป็นสมาชิกของคลาส (เช่นด้านบน) คุณต้องเปลี่ยน__FUNCTION__เป็น__METHOD__


3

นอกจากนี้คุณสามารถใช้The Symfony Serializer Component

use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

$serializer = new Serializer([new ObjectNormalizer()], [new JsonEncoder()]);
$array = json_decode($serializer->serialize($object, 'json'), true);

3

สำหรับกรณีของคุณมันถูก / สวยงามถ้าคุณจะใช้รูปแบบ "มัณฑนากร" หรือ "การเปลี่ยนรูปแบบวันที่" ตัวอย่างเช่น:

โมเดลของคุณ

class Car {
    /** @var int */
    private $color;

    /** @var string */
    private $model;

    /** @var string */
    private $type;

    /**
     * @return int
     */
    public function getColor(): int
    {
        return $this->color;
    }

    /**
     * @param int $color
     * @return Car
     */
    public function setColor(int $color): Car
    {
        $this->color = $color;
        return $this;
    }

    /**
     * @return string
     */
    public function getModel(): string
    {
        return $this->model;
    }

    /**
     * @param string $model
     * @return Car
     */
    public function setModel(string $model): Car
    {
        $this->model = $model;

        return $this;
    }

    /**
     * @return string
     */
    public function getType(): string
    {
        return $this->type;
    }

    /**
     * @param string $type
     * @return Car
     */
    public function setType(string $type): Car
    {
        $this->type = $type;

        return $this;
    }
}

มัณฑนากร

class CarArrayDecorator
{
    /** @var Car */
    private $car;

    /**
     * CarArrayDecorator constructor.
     * @param Car $car
     */
    public function __construct(Car $car)
    {
        $this->car = $car;
    }

    /**
     * @return array
     */
    public function getArray(): array
    {
        return [
            'color' => $this->car->getColor(),
            'type' => $this->car->getType(),
            'model' => $this->car->getModel(),
        ];
    }
}

การใช้

$car = new Car();
$car->setType('type#');
$car->setModel('model#1');
$car->setColor(255);

$carDecorator = new CarArrayDecorator($car);
$carResponseData = $carDecorator->getArray();

ดังนั้นมันจะสวยงามและรหัสที่ถูกต้องมากขึ้น


3

การแปลงและลบดาวที่น่ารำคาญ:

$array = (array) $object;
foreach($array as $key => $val)
{
    $new_array[str_replace('*_', '', $key)] = $val;
}

อาจจะถูกกว่าการใช้การสะท้อน


2

คำตอบสั้น ๆ ของ @ SpYk3HH

function objectToArray($o)
{
    $a = array();
    foreach ($o as $k => $v)
        $a[$k] = (is_array($v) || is_object($v)) ? objectToArray($v): $v;

    return $a;
}

2

เนื่องจากผู้คนจำนวนมากพบคำถามนี้เนื่องจากมีปัญหาเกี่ยวกับคุณลักษณะการเข้าถึงแบบไดนามิกของวัตถุฉันจะชี้ให้เห็นว่าคุณสามารถทำได้ใน PHP: $valueRow->{"valueName"}

ในบริบท (ลบ HTML output เพื่อให้สามารถอ่านได้):

$valueRows = json_decode("{...}"); // Rows of unordered values decoded from a JSON object

foreach ($valueRows as $valueRow) {

    foreach ($references as $reference) {

        if (isset($valueRow->{$reference->valueName})) {
            $tableHtml .= $valueRow->{$reference->valueName};
        }
        else {
            $tableHtml .= " ";
        }
    }
}

2

ด้วยการใช้ typecasting คุณสามารถแก้ไขปัญหาของคุณได้ เพียงเพิ่มบรรทัดต่อไปนี้ไปยังวัตถุส่งคืนของคุณ:

$arrObj = array(yourReturnedObject);

คุณยังสามารถเพิ่มคู่คีย์และค่าใหม่โดยใช้:

$arrObj['key'] = value;

2

ฉันคิดว่ามันเป็นความคิดที่ดีที่จะใช้คุณสมบัติในการจัดเก็บการแปลงเชิงตรรกะกับวัตถุ ตัวอย่างง่ายๆ:

trait ArrayAwareTrait
{
    /**
     * Return list of Entity's parameters
     * @return array
     */
    public function toArray()
    {
        $props = array_flip($this->getPropertiesList());
        return array_map(
            function ($item) {
                if ($item instanceof \DateTime) {
                    return $item->format(DATE_ATOM);
                }
                return $item;
            },
            array_filter(get_object_vars($this), function ($key) use ($props) {
                return array_key_exists($key, $props);
            }, ARRAY_FILTER_USE_KEY)
        );
    }


    /**
     * @return array
     */
    protected function getPropertiesList()
    {
        if (method_exists($this, '__sleep')) {
            return $this->__sleep();
        }
        if (defined('static::PROPERTIES')) {
            return static::PROPERTIES;
        }
        return [];
    }
}

class OrderResponse
{
    use ArrayAwareTrait;

    const PROP_ORDER_ID = 'orderId';
    const PROP_TITLE = 'title';
    const PROP_QUANTITY = 'quantity';
    const PROP_BUYER_USERNAME = 'buyerUsername';
    const PROP_COST_VALUE = 'costValue';
    const PROP_ADDRESS = 'address';

    private $orderId;
    private $title;
    private $quantity;
    private $buyerUsername;
    private $costValue;
    private $address;

    /**
     * @param $orderId
     * @param $title
     * @param $quantity
     * @param $buyerUsername
     * @param $costValue
     * @param $address
     */
    public function __construct(
        $orderId,
        $title,
        $quantity,
        $buyerUsername,
        $costValue,
        $address
    ) {
        $this->orderId = $orderId;
        $this->title = $title;
        $this->quantity = $quantity;
        $this->buyerUsername = $buyerUsername;
        $this->costValue = $costValue;
        $this->address = $address;
    }

    /**
     * @inheritDoc
     */
    public function __sleep()
    {
        return [
            static::PROP_ORDER_ID,
            static::PROP_TITLE,
            static::PROP_QUANTITY,
            static::PROP_BUYER_USERNAME,
            static::PROP_COST_VALUE,
            static::PROP_ADDRESS,
        ];
    }

    /**
     * @return mixed
     */
    public function getOrderId()
    {
        return $this->orderId;
    }

    /**
     * @return mixed
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * @return mixed
     */
    public function getQuantity()
    {
        return $this->quantity;
    }

    /**
     * @return mixed
     */
    public function getBuyerUsername()
    {
        return $this->buyerUsername;
    }

    /**
     * @return mixed
     */
    public function getCostValue()
    {
        return $this->costValue;
    }

    /**
     * @return string
     */
    public function getAddress()
    {
        return $this->address;
    }
}

$orderResponse = new OrderResponse(...);
var_dump($orderResponse->toArray());

1
$Menu = new Admin_Model_DbTable_Menu(); 
$row = $Menu->fetchRow($Menu->select()->where('id = ?', $id));
$Addmenu = new Admin_Form_Addmenu(); 
$Addmenu->populate($row->toArray());

ฉันสมมติว่าคำตอบนี้สำหรับบันทึกหลักคำสอน (หรือคล้ายกัน)
nikoskip

1

นี่ฉันได้ทำobjectToArray ()วิธีการซึ่งยังทำงานร่วมกับวัตถุ recursive เช่นเมื่อ$objectAมีที่จุดอีกครั้งเพื่อ$objectB$objectA

นอกจากนี้ฉันได้ จำกัด การส่งออกไปยังคุณสมบัติสาธารณะโดยใช้ ReflectionClass กำจัดมันถ้าคุณไม่ต้องการมัน

    /**
     * Converts given object to array, recursively.
     * Just outputs public properties.
     *
     * @param object|array $object
     * @return array|string
     */
    protected function objectToArray($object) {
        if (in_array($object, $this->usedObjects, TRUE)) {
            return '**recursive**';
        }
        if (is_array($object) || is_object($object)) {
            if (is_object($object)) {
                $this->usedObjects[] = $object;
            }
            $result = array();
            $reflectorClass = new \ReflectionClass(get_class($this));
            foreach ($object as $key => $value) {
                if ($reflectorClass->hasProperty($key) && $reflectorClass->getProperty($key)->isPublic()) {
                    $result[$key] = $this->objectToArray($value);
                }
            }
            return $result;
        }
        return $object;
    }

เมื่อต้องการระบุวัตถุที่ใช้แล้วฉันกำลังใช้คุณสมบัติที่มีการป้องกันในชื่อคลาส (นามธรรม) $this->usedObjectsนี้ หากวัตถุที่ซ้อนกัน recursive **recursive**พบก็จะถูกแทนที่ด้วยสตริง มิฉะนั้นจะล้มเหลวเนื่องจากลูปไม่สิ้นสุด


$usedObjectsไม่ได้เริ่มต้นที่การเริ่มต้นดังนั้นการเรียกหลาย ๆ ครั้งนี้จะให้ผลลัพธ์ที่ไม่ถูกต้องในการโทรในภายหลัง นอกจากนี้คุณจะไม่ทำให้มันว่างในตอนท้ายดังนั้นวัตถุของคุณจะไม่ถูกลบออกจากหน่วยความจำ
HappyDog

1

มีข้อเสนอของฉันคือถ้าคุณมีวัตถุในวัตถุที่มีสมาชิกส่วนตัว:

public function dismount($object) {
    $reflectionClass = new \ReflectionClass(get_class($object));
    $array = array();
    foreach ($reflectionClass->getProperties() as $property) {
        $property->setAccessible(true);
        if (is_object($property->getValue($object))) {
            $array[$property->getName()] = $this->dismount($property->getValue($object));
        } else {
            $array[$property->getName()] = $property->getValue($object);
        }
        $property->setAccessible(false);
    }
    return $array;
}

1

ฉันใช้สิ่งนี้ (ต้องการโซลูชันแบบเรียกซ้ำพร้อมกุญแจที่เหมาะสม):

    /**
     * This method returns the array corresponding to an object, including non public members.
     *
     * If the deep flag is true, is will operate recursively, otherwise (if false) just at the first level.
     *
     * @param object $obj
     * @param bool $deep = true
     * @return array
     * @throws \Exception
     */
    public static function objectToArray(object $obj, bool $deep = true)
    {
        $reflectionClass = new \ReflectionClass(get_class($obj));
        $array = [];
        foreach ($reflectionClass->getProperties() as $property) {
            $property->setAccessible(true);
            $val = $property->getValue($obj);
            if (true === $deep && is_object($val)) {
                $val = self::objectToArray($val);
            }
            $array[$property->getName()] = $val;
            $property->setAccessible(false);
        }
        return $array;
    }

ตัวอย่างการใช้งานรหัสต่อไปนี้:

class AA{
    public $bb = null;
    protected $one = 11;

}

class BB{
    protected $two = 22;
}


$a = new AA();
$b = new BB();
$a->bb = $b;

var_dump($a)

จะพิมพ์สิ่งนี้:

array(2) {
  ["bb"] => array(1) {
    ["two"] => int(22)
  }
  ["one"] => int(11)
}

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