Converting a PHP array to class variables

后端 未结 6 1571
说谎
说谎 2020-12-07 10:01

Simple question, how do I convert an associative array to variables in a class? I know there is casting to do an (object) $myarray or whatever it is, but that w

相关标签:
6条回答
  • 2020-12-07 10:38

    Here's another solution using PDOStatement::fetchObject, though it is a bit of a hack.

    $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);
    
    0 讨论(0)
  • 2020-12-07 10:46

    Best solution is to have trait with static function fromArray that can be used for data loading:

    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;
      }
    }
    

    Then you can use this trait like that:

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

    Then you can call static fromArray function to get new instance of Example class:

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

    I also have much more sophisticated version with nesting and value filtering https://github.com/OzzyCzech/fromArray

    0 讨论(0)
  • 2020-12-07 10:54

    If you want to cast nested array to object use this code:

    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;
        }
    }
    

    Then you can use like this:

    $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
    
    0 讨论(0)
  • 2020-12-07 10:54

    Define a static method to convert get an instance from an array. Best, define an interface for it. This is declarative, does not pollute the constructor, allows you to set private properties and still implement custom logic that would not be possible with Reflection. If you want a generic solution, define a trait and use it in your classes.

    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);
    }
    
    0 讨论(0)
  • 2020-12-07 10:59

    This simple code should work:

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

    Example usage

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

    Alternatively, this might be a better approach

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

    Usage is the same

    // 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
    
    0 讨论(0)
  • if you (like me) came here looking for a source code generator for array->class, i couldn't really find any, and then i came up with this (a work in progress, not well tested or anything, json_decode returns the array.):

    <?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 ) );
    }
    

    output:

    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;
    }
    
    0 讨论(0)
提交回复
热议问题