2010-04-26 40 views
24

Câu hỏi đơn giản, làm thế nào để chuyển đổi một mảng kết hợp thành các biến trong một lớp? Tôi biết có đúc để làm một (object) $myarray hoặc bất cứ điều gì nó được, nhưng điều đó sẽ tạo ra một stdClass mới và không giúp tôi nhiều. Có bất kỳ phương thức một hoặc hai dòng đơn giản nào để tạo mỗi cặp $key => $value trong mảng của tôi thành biến số $key = $value cho lớp của tôi không? Tôi không tìm thấy nó rất hợp lý để sử dụng một vòng lặp foreach cho điều này, tôi muốn được tốt hơn off chỉ chuyển đổi nó thành một stdClass và lưu trữ trong một biến, phải không?Chuyển đổi một mảng PHP thành các biến lớp

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

Trả lời

59

mã đơn giản này sẽ làm việc:

<?php 

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

?> 

sử dụng Ví dụ

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

Ngoài ra, đây có thể là một cách tiếp cận tốt hơn

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

?> 

Cách sử dụng là như nhau

// 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

Đừng nghĩ rằng bạn cần {} trong $ this -> {$ key} = $ value; tuyên bố – AntonioCS

+13

@AntonioCS, nó không cần thiết nhưng nó chắc chắn nhấn mạnh sự truy cập của một thuộc tính có tên biến. Nó cũng chứng tỏ rằng '{}' có thể được sử dụng khi thuộc tính biến trở nên phức tạp hơn; ví dụ: '$ this -> {$ this-> foo ('bar')} -> do_something();' –

+0

Thực sự là hai giải pháp tốt đẹp. Tôi không biết về những phương pháp ma thuật, thủ thuật gọn gàng. – John

1

Đây là một giải pháp sử dụng PDOStatement::fetchObject, mặc dù nó là một chút của một 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

Xác định phương pháp tĩnh để chuyển đổi lấy một thể hiện từ mảng. Tốt nhất, xác định một giao diện cho nó. Đây là khai báo, không gây ô nhiễm cho hàm tạo, cho phép bạn thiết lập các thuộc tính riêng tư và vẫn thực hiện logic tùy chỉnh mà sẽ không thể thực hiện được với Reflection. Nếu bạn muốn có một giải pháp chung, hãy xác định một đặc tính và sử dụng nó trong các lớp của bạn.

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

nếu bạn (như tôi) đến đây tìm kiếm một bộ tạo mã nguồn cho array-> lớp, tôi thực sự không thể tìm thấy bất kỳ, và sau đó tôi đã đưa ra với điều này (một tác phẩm trong tiến trình, không tốt kiểm tra hoặc bất cứ điều gì, json_decode trả về mảng.):

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

đầu ra:

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

Nếu bạn muốn cast mảng lồng nhau để phản đối sử dụng mã này:

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

Sau đó, bạn có thể sử dụng như thế này:

$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

Giải pháp tốt nhất là có trait với chức năng tĩnh fromArray có thể được sử dụng cho các dữ liệu tải:

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

Sau đó, bạn có thể sử dụng đặc điểm này như thế:

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

Sau đó, bạn có thể gọi tĩnh fromArray chức năng để có được thể hiện mới của lớp Ví dụ:

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

tôi cũng có nhiều phức tạp hơn phiên bản với làm tổ và giá trị lọc https://github.com/OzzyCzech/fromArray

Các vấn đề liên quan