2010-04-26 10 views
24

Pregunta simple, ¿cómo convierto un conjunto asociativo a variables en una clase? Sé que hay un casting para hacer un (object) $myarray o lo que sea, pero eso creará un nuevo stdClass y no me ayuda mucho. ¿Hay algún método sencillo de una o dos líneas para hacer cada par de $key => $value en mi matriz en una variable $key = $value para mi clase? No me parece muy lógico utilizar un bucle foreach para esto, sería mejor simplemente convertirlo en stdClass y almacenarlo en una variable, ¿no?Conversión de un conjunto de PHP a variables de clase

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

Respuesta

59

Este código simple debería funcionar:

<?php 

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

?> 

Ejemplo de uso

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

Alternativamente, esto podría ser un mejor enfoque

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

?> 

El uso es el mismo

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

No creo que necesite el {} en el valor $ this -> {$ key} = $; declaración – AntonioCS

+13

@AntonioCS, no es necesario pero definitivamente enfatiza el acceso de una propiedad de nombre variable. También demuestra que '{}' se puede usar cuando la propiedad variable se vuelve más compleja; por ejemplo, '$ this -> {$ this-> foo ('bar')} -> do_something();' –

+0

Realmente dos buenas soluciones. No tenía conocimiento de esos métodos mágicos, buenos trucos. – John

1

Aquí hay otra solución utilizando PDOStatement::fetchObject, aunque es un poco de un truco.

$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

definir un método estático para convertir obtener una instancia de una matriz. Mejor, defina una interfaz para eso. Esto es declarativo, no contamina el constructor, le permite establecer propiedades privadas y aún implementar una lógica personalizada que no sería posible con Reflection. Si desea una solución genérica, defina un rasgo y úselo en sus clases.

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

si (como yo) vinieron aquí en busca de un generador de código fuente para Expandido> clase, realmente no podía encontrar ninguna, y luego se me ocurrió esto (un trabajo en progreso, no está bien probado o cualquier cosa, json_decode devuelve la matriz.):

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

de salida:

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

Si quieres lanzar matriz anidada de objetar el uso de este código:

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

continuación, puede utilizar la siguiente manera:

$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

La mejor solución es tener trait con la función estática fromArray que puede ser utilizado para la carga de datos:

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

continuación, puede utilizar esta característica de esa manera:

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

A continuación, puede llamar a la función estática fromArray para obtener nueva instancia de la clase Ejemplo:

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

que también tienen mucho más sofisticada versión con el filtrado de anidación y el valor https://github.com/OzzyCzech/fromArray

Cuestiones relacionadas