代码之家  ›  专栏  ›  技术社区  ›  animuson Hemanshu

将PHP数组转换为类变量

  •  25
  • animuson Hemanshu  · 技术社区  · 14 年前

    简单的问题,如何将关联数组转换为类中的变量?我知道有演员要演 (object) $myarray 或者不管它是什么,但这将创建一个新的stdclass,对我没有多大帮助。有简单的一条或两条线的方法吗 $key => $value 在我的数组中配对成 $key = $value 我班的变量?我觉得用foreach循环来处理这个问题不太合理,我最好把它转换成stdclass并将其存储在变量中,不是吗?

    class MyClass {
        var $myvar; // I want variables like this, so they can be references as $this->myvar
        function __construct($myarray) {
            // a function to put my array into variables
        }
    }
    
    6 回复  |  直到 7 年前
        1
  •  64
  •   maček    14 年前

    这个简单的代码应该可以工作:

    <?php
    
      class MyClass {
        public function __construct(Array $properties=array()){
          foreach($properties as $key => $value){
            $this->{$key} = $value;
          }
        }
      }
    
    ?>
    

    示例用法

    $foo = new MyClass(array("hello" => "world"));
    $foo->hello // => "world"
    

    或者,这可能是一种更好的方法

    <?php
    
      class MyClass {
    
        private $_data;
    
        public function __construct(Array $properties=array()){
          $this->_data = $properties;
        }
    
        // magic methods!
        public function __set($property, $value){
          return $this->_data[$property] = $value;
        }
    
        public function __get($property){
          return array_key_exists($property, $this->_data)
            ? $this->_data[$property]
            : null
          ;
        }
      }
    
    ?>
    

    用法相同

    // init
    $foo = new MyClass(array("hello" => "world"));
    $foo->hello;          // => "world"
    
    // set: this calls __set()
    $foo->invader = "zim";
    
    // get: this calls __get()
    $foo->invader;       // => "zim"
    
    // attempt to get a data[key] that isn't set
    $foo->invalid;       // => null
    
        2
  •  2
  •   OzzyCzech    7 年前

    最好的解决办法是 trait 具有静态功能 fromArray 可用于数据加载:

    trait FromArray {
     public static function fromArray(array $data = []) {
       foreach (get_object_vars($obj = new self) as $property => $default) {
         if (!array_key_exists($property, $data)) continue;
         $obj->{$property} = $data[$property]; // assign value to object
       }
       return $obj;
      }
    }
    

    然后你可以使用这样的特性:

    class Example {
      use FromArray;
      public $data;
      public $prop;
    }
    

    然后可以调用static 从数组 函数以获取示例类的新实例:

    $obj = Example::fromArray(['data' => 123, 'prop' => false]);
    var_dump($obj);
    

    我还有更复杂的嵌套和值过滤版本 https://github.com/OzzyCzech/fromArray

        3
  •  1
  •   Jonathan Amend    10 年前

    这是另一个解决方案 PDOStatement::fetchObject 尽管这有点像黑客。

    $array = array('property1' => 'value1', 'property2' => 'value2');
    $className = 'MyClass';
    
    $pdo = new PDO('sqlite::memory:'); // we don't actually need sqlite; any PDO connection will do
    $select = 'SELECT ? AS property1, ? AS property2'; // this could also be built from the array keys
    $statement = $pdo->prepare($select);
    
    // this last part can also be re-used in a loop
    $statement->execute(array_values($array));
    $myObject = $statement->fetchObject($className);
    
        4
  •  0
  •   felixfbecker    8 年前

    定义一个静态方法来转换从数组中获取实例。最好,为它定义一个接口。这是声明性的,不会污染构造函数,允许您设置私有属性,并且仍然实现反射不可能实现的自定义逻辑。如果你想要一个通用的解决方案,定义一个特性并在你的类中使用它。

    class Test implements ContructableFromArray {
       private $property;
       public static function fromArray(array $array) {
           $instance = new self();
           $instance->property = $array['property'];
           return $instance;
       }
    }
    
    interface ConstructableFromArray {
       public static function fromArray(array $array);
    }
    
        5
  •  0
  •   hanshenrik    7 年前

    如果您(像我一样)来这里为array->类寻找源代码生成器,我真的找不到任何源代码生成器,然后我想到了这一点(一项正在进行的工作,没有经过很好的测试或其他任何事情,json_decode返回数组。):

    <?php
    declare(strict_types = 1);
    
    $json = <<<'JSON'
    {"object_kind":"push","event_name":"push","before":"657dbca6668a99012952c58e8c8072d338b48d20","after":"5ac3eda70dbb44bfdf98a3db87515864036db0f9","ref":"refs/heads/master","checkout_sha":"5ac3eda70dbb44bfdf98a3db87515864036db0f9","message":null,"user_id":805411,"user_name":"hanshenrik","user_email":"divinity76@gmail.com","user_avatar":"https://secure.gravatar.com/avatar/e3af2bd4b5604b0b661b5e6646544eba?s=80\u0026d=identicon","project_id":3498684,"project":{"name":"gitlab_integration_tests","description":"","web_url":"https://gitlab.com/divinity76/gitlab_integration_tests","avatar_url":null,"git_ssh_url":"git@gitlab.com:divinity76/gitlab_integration_tests.git","git_http_url":"https://gitlab.com/divinity76/gitlab_integration_tests.git","namespace":"divinity76","visibility_level":0,"path_with_namespace":"divinity76/gitlab_integration_tests","default_branch":"master","homepage":"https://gitlab.com/divinity76/gitlab_integration_tests","url":"git@gitlab.com:divinity76/gitlab_integration_tests.git","ssh_url":"git@gitlab.com:divinity76/gitlab_integration_tests.git","http_url":"https://gitlab.com/divinity76/gitlab_integration_tests.git"},"commits":[{"id":"5ac3eda70dbb44bfdf98a3db87515864036db0f9","message":"dsf\n","timestamp":"2017-06-14T02:21:50+02:00","url":"https://gitlab.com/divinity76/gitlab_integration_tests/commit/5ac3eda70dbb44bfdf98a3db87515864036db0f9","author":{"name":"hanshenrik","email":"divinity76@gmail.com"},"added":[],"modified":["gitlab_callback_page.php"],"removed":[]}],"total_commits_count":1,"repository":{"name":"gitlab_integration_tests","url":"git@gitlab.com:divinity76/gitlab_integration_tests.git","description":"","homepage":"https://gitlab.com/divinity76/gitlab_integration_tests","git_http_url":"https://gitlab.com/divinity76/gitlab_integration_tests.git","git_ssh_url":"git@gitlab.com:divinity76/gitlab_integration_tests.git","visibility_level":0}}        
    JSON;
    $arr = json_decode ( $json, true );
    
    var_dump ( array_to_class ( $arr ) );
    
    /**
     *
     * @param array $arr            
     * @param string $top_class_name            
     */
    function array_to_class(array $arr, string $top_class_name = "TopClass"): string {
        $top_class_name = ucfirst ( $top_class_name );
        $classes = array (); // deduplicated 'definition'=>true,array_keys();
        $internal = function (array $arr, string $top_class_name) use (&$classes, &$internal) {
            $curr = 'Class ' . $top_class_name . ' {' . "\n";
            foreach ( $arr as $key => $val ) {
                $type = gettype ( $val );
                if (is_array ( $val )) {
                    $type = ucfirst ( ( string ) $key );
                    $classes [$internal ( $val, ( string ) $key )] = true;
                }
                $curr .= <<<FOO
        /**
         * @property $type \$$key
        */
    FOO;
                $curr .= "\n    public $" . $key . ";\n";
            }
            $curr .= '}';
            $classes [$curr] = true;
        };
        $internal ( $arr, $top_class_name );
        return implode ( "\n", array_keys ( $classes ) );
    }
    

    输出:

    Class project {
        /**
         * @property string $name
        */
        public $name;
        /**
         * @property string $description
        */
        public $description;
        /**
         * @property string $web_url
        */
        public $web_url;
        /**
         * @property NULL $avatar_url
        */
        public $avatar_url;
        /**
         * @property string $git_ssh_url
        */
        public $git_ssh_url;
        /**
         * @property string $git_http_url
        */
        public $git_http_url;
        /**
         * @property string $namespace
        */
        public $namespace;
        /**
         * @property integer $visibility_level
        */
        public $visibility_level;
        /**
         * @property string $path_with_namespace
        */
        public $path_with_namespace;
        /**
         * @property string $default_branch
        */
        public $default_branch;
        /**
         * @property string $homepage
        */
        public $homepage;
        /**
         * @property string $url
        */
        public $url;
        /**
         * @property string $ssh_url
        */
        public $ssh_url;
        /**
         * @property string $http_url
        */
        public $http_url;
    }
    
    Class author {
        /**
         * @property string $name
        */
        public $name;
        /**
         * @property string $email
        */
        public $email;
    }
    Class added {
    }
    Class modified {
        /**
         * @property string $0
        */
        public $0;
    }
    Class removed {
    }
    Class 0 {
        /**
         * @property string $id
        */
        public $id;
        /**
         * @property string $message
        */
        public $message;
        /**
         * @property string $timestamp
        */
        public $timestamp;
        /**
         * @property string $url
        */
        public $url;
        /**
         * @property Author $author
        */
        public $author;
        /**
         * @property Added $added
        */
        public $added;
        /**
         * @property Modified $modified
        */
        public $modified;
        /**
         * @property Removed $removed
        */
        public $removed;
    }
    Class commits {
        /**
         * @property 0 $0
        */
        public $0;
    }
    Class repository {
        /**
         * @property string $name
        */
        public $name;
        /**
         * @property string $url
        */
        public $url;
        /**
         * @property string $description
        */
        public $description;
        /**
         * @property string $homepage
        */
        public $homepage;
        /**
         * @property string $git_http_url
        */
        public $git_http_url;
        /**
         * @property string $git_ssh_url
        */
        public $git_ssh_url;
        /**
         * @property integer $visibility_level
        */
        public $visibility_level;
    }
    Class TopClass {
        /**
         * @property string $object_kind
        */
        public $object_kind;
        /**
         * @property string $event_name
        */
        public $event_name;
        /**
         * @property string $before
        */
        public $before;
        /**
         * @property string $after
        */
        public $after;
        /**
         * @property string $ref
        */
        public $ref;
        /**
         * @property string $checkout_sha
        */
        public $checkout_sha;
        /**
         * @property NULL $message
        */
        public $message;
        /**
         * @property integer $user_id
        */
        public $user_id;
        /**
         * @property string $user_name
        */
        public $user_name;
        /**
         * @property string $user_email
        */
        public $user_email;
        /**
         * @property string $user_avatar
        */
        public $user_avatar;
        /**
         * @property integer $project_id
        */
        public $project_id;
        /**
         * @property Project $project
        */
        public $project;
        /**
         * @property Commits $commits
        */
        public $commits;
        /**
         * @property integer $total_commits_count
        */
        public $total_commits_count;
        /**
         * @property Repository $repository
        */
        public $repository;
    }
    
        6
  •  0
  •   M Rostami    7 年前

    如果要将嵌套数组强制转换为对象,请使用以下代码:

    class ToObject
    {
        private $_data;
    
        public function __construct(array $data)
        {
            $this->setData($data);
        }
    
        /**
         * @return array
         */
        public function getData()
        {
            return $this->_data;
        }
    
        /**
         * @param array $data
         */
        public function setData(array $data)
        {
            $this->_data = $data;
            return $this;
        }
    
        public function __call($property, $args)
        {
            // NOTE: change lcfirst if you need (ucfirst/...) or put all together
            $property = lcfirst(str_replace('get', '', $property));
            if (array_key_exists($property, $this->_data)) {
                if (is_array($this->_data[$property])) {
                    return new self($this->_data[$property]);
                }
                return $this->_data[$property];
            }
            return null;
        }
    }
    

    然后您可以这样使用:

    $array = [
        'first' => '1.1',
        'second' => [
            'first' => '2.1',
            'second' => '2.2',
            'third' => [
                'first' => '2.3.1'
            ]
        ]
    ];
    $object = new ToObject($array);
    $object->getFirst(); // returns 1.1
    $object->getSecond()->getFirst(); // returns 2.1
    $object->getSecond()->getData(); // returns second array
    $object->getSecond()->getThird()->getFirst(); // returns 2.3.1