将 PHP 数组转换为类变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2715465/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 07:27:58  来源:igfitidea点击:

Converting a PHP array to class variables

phparraysclassvariablesobject

提问by animuson

Simple question, how do I convert an associative array to variables in a class? I know there is casting to do an (object) $myarrayor whatever it is, but that will create a new stdClass and doesn't help me much. Are there any easy one or two line methods to make each $key => $valuepair in my array into a $key = $valuevariable for my class? I don't find it very logical to use a foreach loop for this, I'd be better off just converting it to a stdClass and storing that in a variable, wouldn't I?

一个简单的问题,如何将关联数组转换为类中的变量?我知道有铸造来做一个(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
    }
}

回答by ma?ek

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

回答by OzzyCzech

Best solution is to have traitwith static function fromArraythat can be used for data loading:

最好的解决方案是具有可用于数据加载的静态函数的特征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;
  }
}

Then you can use this trait like that:

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

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

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

然后你可以调用静态fromArray函数来获取 Example 类的新实例:

$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

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

回答by Jonathan Amend

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

这是使用 的另一种解决方案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);

回答by felixfbecker

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

回答by hanshenrik

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.):

如果你(像我一样)来这里寻找 array->class 的源代码生成器,我真的找不到,然后我想出了这个(正在进行的工作,没有经过很好的测试或任何东西,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":"[email protected]","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":"[email protected]: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":"[email protected]:divinity76/gitlab_integration_tests.git","ssh_url":"[email protected]: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":"[email protected]"},"added":[],"modified":["gitlab_callback_page.php"],"removed":[]}],"total_commits_count":1,"repository":{"name":"gitlab_integration_tests","url":"[email protected]: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":"[email protected]: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 
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;
    }
}
*/ public
$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
; } 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 ##代码## */ public ##代码##; } 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; }

回答by M Rostami

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

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

##代码##

Then you can use like this:

然后你可以像这样使用:

##代码##