Простой вопрос, как преобразовать ассоциативный массив в переменные в классе? Я знаю, что есть кастинг, чтобы сделать (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 } }
Этот простой код должен работать:
<?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
Вот еще одно решение, использующее PDOStatement::fetchObject
, хотя это немного 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);
Определите статический метод для преобразования, чтобы получить экземпляр из массива. Лучше всего, определите для него интерфейс. Это декларативно, не загрязняет конструктор, позволяет вам устанавливать частные свойства и по-прежнему выполнять пользовательскую логику, которая не была бы возможна с Reflection. Если вы хотите получить общее решение, определите его и используйте его в своих классах.
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); }
если вы (как я) пришли сюда искать генератор исходного кода для 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":"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; }
Если вы хотите, чтобы вложенный массив в объект использовал этот код:
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
Лучшее решение – иметь свойство статической функции 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 fromArray
для получения нового экземпляра класса Example:
$obj = Example::fromArray(['data' => 123, 'prop' => false]); var_dump($obj);
У меня также есть гораздо более сложная версия с вложением и фильтрацией значений https://github.com/OzzyCzech/fromArray