How to convert (cast) Object to Array without Class Name prefix in PHP?

后端 未结 4 633
被撕碎了的回忆
被撕碎了的回忆 2021-02-10 11:16

How to convert (cast) Object to Array without Class Name prefix in PHP?

class Teste{

    private $a;
    private $b;

    function __construct($a, $b) {
                


        
相关标签:
4条回答
  • 2021-02-10 11:48

    As far as I know, PHP doesn't have a simple way to do what you want. Most languages don't. You should look into reflection. Take a look at this document: http://www.php.net/manual/en/reflectionclass.getproperties.php

    I've made a function that should work as expected:

    function objectToArr($obj)
    {
        $result = array();
        ReflectionClass $cls = new ReflectionClass($obj);
        $props = $cls->getProperties();
        foreach ($props as $prop)
        {
            $result[$prop->getName()] = $prop->getValue($obj);
        }
    }
    
    0 讨论(0)
  • 2021-02-10 11:55

    You can use Reflection to solve this task. But as usual this is a strong indicator that your class design is somewhat broken. However:

    function objectToArray($obj) {
        // Create a reflection object
        $refl = new ReflectionClass($obj);
    
        // Retrieve the properties and strip the ReflectionProperty objects down
        // to their values, accessing even private members.
        return array_map(function($prop) use ($obj) {
            $prop->setAccessible(true);
            return $prop->getValue($obj);
        }, $refl->getProperties());
    }
    
    // Usage:
    $arr = objectToArray( new Foo() );
    
    0 讨论(0)
  • 2021-02-10 11:56

    From the manual:

    If an object is converted to an array, the result is an array whose elements are the object's properties. The keys are the member variable names, with a few notable exceptions: integer properties are unaccessible; private variables have the class name prepended to the variable name; protected variables have a '*' prepended to the variable name. These prepended values have null bytes on either side. This can result in some unexpected behaviour:

    You can therefore work around the issue like this:

    $temp = (array)(new Teste('foo','bar'));
    $array = array();
    foreach ($temp as $k => $v) {
      $k = preg_match('/^\x00(?:.*?)\x00(.+)/', $k, $matches) ? $matches[1] : $k;
      $array[$k] = $v;
    }
    var_dump($array);
    

    It does seem odd that there is no way to control/disable this behaviour, since there is no risk of collisions.

    0 讨论(0)
  • 2021-02-10 12:02

    The "class name prefix" is part of the (internal) name of the property. Because you declared both as private PHP needs something to distinguish this from properties $a and $b of any subclass.

    The easiest way to bypass it: Don't make them private. You can declare them as protected instead.

    However, this isn't a solution in every case, because usually one declares something as private with an intention. I recommend to implement a method, that makes the conversion for you. This gives you even more control on how the resulting array looks like

    public function toArray() {
      return array(
        'a' => $this->a,
        'b' => $this->b
      );
    }
    
    0 讨论(0)
提交回复
热议问题