web-dev-qa-db-fra.com

Conversion d'un PHP tableau de variables de classe

Question simple, comment convertir un tableau associatif en variables dans une classe? Je sais qu'il existe un casting pour faire un (object) $myarray ou quoi que ce soit d'autre, mais cela va créer une nouvelle classe stdClass et ne m'aide pas beaucoup. Existe-t-il des méthodes simples à une ou deux lignes permettant de transformer chaque paire $key => $value de mon tableau en une variable $key = $value pour ma classe? Je ne trouve pas très logique d'utiliser une boucle foreach pour cela, il vaudrait mieux la convertir en stdClass et la stocker dans une variable, n'est-ce pas?

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

Ce code simple devrait fonctionner:

<?php

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

?>

Exemple d'utilisation

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

Alternativement, cela pourrait être une meilleure approche

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

?>

L'utilisation est la même

// 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
64
maček

La meilleure solution consiste à avoir trait avec la fonction statique fromArray pouvant être utilisée pour le chargement de données:

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

Ensuite, vous pouvez utiliser ce trait comme ça:

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

Ensuite, vous pouvez appeler la fonction statique fromArray pour obtenir une nouvelle instance de la classe Example: 

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

J'ai aussi une version beaucoup plus sophistiquée avec imbrication et filtrage des valeurs https://github.com/OzzyCzech/fromArray

2
OzzyCzech

Voici une autre solution utilisant PDOStatement::fetchObject, bien que ce soit un peu un bidouillage.

$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);
1
Jonathan Amend

si vous (comme moi) êtes venu ici à la recherche d'un générateur de code source pour array-> class, je ne pourrais pas en trouver vraiment, puis je l'ai trouvé (travail en cours, pas bien testé ou quoi que ce soit, json_decode renvoie le tableau.):

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

sortie:

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
hanshenrik

Si vous voulez convertir un tableau imbriqué en objet, utilisez ce 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;
    }
}

Ensuite, vous pouvez utiliser comme ceci: 

$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
Mohamad Rostami

Définissez une méthode statique pour convertir obtenir une instance d'un tableau. Mieux, définissez une interface pour cela. Ceci est déclaratif, ne pollue pas le constructeur, vous permet de définir des propriétés privées tout en implémentant une logique personnalisée impossible avec Reflection. Si vous voulez une solution générique, définissez un trait et utilisez-le dans vos 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
felixfbecker