59 votes

Pouvez-vous créer des propriétés d'instance dynamiquement en PHP?

Est-il possible de créer toutes les propriétés de l'occurrence de façon dynamique? Par exemple, je voudrais être en mesure de générer tous les attributs dans le constructeur et toujours être en mesure d'y accéder après la classe est instanciée comme ceci: $object->property. Notez que je veux accéder aux propriétés séparément, et non pas à l'aide d'un tableau; voici un exemple de ce que je ne veux:

class Thing {
    public $properties;
    function __construct(array $props=array()) {
        $this->properties = $props;
    }
}
$foo = new Thing(array('bar' => 'baz');
# I don't want to have to do this:
$foo->properties['bar'];
# I want to do this:
//$foo->bar;

Pour être plus précis, quand je fais face à des classes qui ont un grand nombre de propriétés, je voudrais être en mesure de sélectionner toutes les colonnes dans une base de données (qui représentent les propriétés) et de créer des propriétés d'une instance à partir d'eux. Chaque valeur de la colonne doit être stocké dans une instance distincte de la propriété.

62voto

Udo Points 1356

En quelque sorte. Il y a de la magie des méthodes qui vous permettent de brancher votre propre code pour la mise en œuvre de la classe de comportement au moment de l'exécution:

class foo {
  public function __get($name) {
    return('dynamic!');
  }
  public function __set($name, $value) {
    $this->internalData[$name] = $value;
  }
}

C'est un exemple de dynamique getter et setter, il vous permet d'exécuter le comportement à chaque fois qu'une propriété de l'objet est accessible. Par exemple

print(new foo()->someProperty);

imprimez, dans ce cas, "dynamique!" et vous pouvez également affecter une valeur à un nommé arbitrairement de la propriété, auquel cas l' __set (), méthode silencieusement invoquée. L' __call($nom, $params) méthode fait de même pour les appels de méthode objet. Très utile dans des cas particuliers. Mais la plupart du temps, vous aurez par avec:

class foo {
  public function __construct() {
    foreach(getSomeDataArray() as $k => $value)
      $this->{$k} = $value;
  }
}

...parce que la plupart du temps tous vous avez besoin est de vider le contenu d'un tableau en conséquence nommé champs de la classe une fois, ou à tout le moins très explicite points dans le chemin d'exécution. Donc, sauf si vous avez vraiment besoin de comportement dynamique, l'utilisation de ce dernier exemple pour remplir un objet avec les données.

Cela s'appelle la surcharge http://php.net/manual/en/language.oop5.overloading.php

23voto

Chad Birch Points 39087

Cela dépend exactement de ce que vous voulez. Pouvez-vous modifier la classe dynamiquement? Pas vraiment. Mais pouvez-vous créer des propriétés d' objet de manière dynamique, comme dans une instance particulière de cette classe? Oui.

 class Test
{
    public function __construct($x)
    {
        $this->{$x} = "dynamic";
    }
}

$a = new Test("bar");
print $a->bar;
 

Les sorties:

dynamique

Ainsi, une propriété d'objet nommée "bar" a été créée dynamiquement dans le constructeur.

7voto

Oui, vous le pouvez.

class test
{
    public function __construct()
    {
    	$arr = array
    	(
    		'column1',
    		'column2',
    		'column3'
    	);

    	foreach ($arr as $key => $value)
    	{
    		$this->$value = '';
    	}	
    }

    public function __set($key, $value)
    {
    	$this->$key = $value;
    }

    public function __get($value)
    {
    	return 'This is __get magic '.$value;
    }
}

$test = new test;

// Results from our constructor test.
var_dump($test);

// Using __set
$test->new = 'variable';
var_dump($test);

// Using __get
print $test->hello;

Sortie

object(test)#1 (3) {
  ["column1"]=>
  string(0) ""
  ["column2"]=>
  string(0) ""
  ["column3"]=>
  string(0) ""
}
object(test)#1 (4) {
  ["column1"]=>
  string(0) ""
  ["column2"]=>
  string(0) ""
  ["column3"]=>
  string(0) ""
  ["new"]=>
  string(8) "variable"
}
This is __get magic hello

Ce code permet de définir des propriétés dynamiques dans le constructeur, qui peut ensuite être consulté avec $this->colonne. C'est aussi une bonne pratique de l'utilisation de l' __get et __set magique méthodes pour faire face à des propriétés qui ne sont pas définis dans la classe. Plus d'informations peuvent être trouvées ici.

http://www.tuxradar.com/practicalphp/6/14/2

http://www.tuxradar.com/practicalphp/6/14/3

7voto

Carlton Gibson Points 2582

Vous pouvez utiliser une variable d'instance pour agir en tant que détenteur de valeurs arbitraires, puis utiliser la méthode magique __get pour les récupérer en tant que propriétés normales:

 class My_Class
{
    private $_properties = array();

    public function __construct(Array $hash)
    {
         $this->_properties = $hash;
    }

    public function __get($name)
    {
         if (array_key_exists($name, $this->_properties)) {
             return $this->_properties[$name];
         }
         return null;
    }
}
 

6voto

srcspider Points 2623

Pourquoi chaque exemple est-il si compliqué?

 <?php namespace example;

error_reporting(E_ALL | E_STRICT); 

class Foo
{
    // class completely empty
}

$testcase = new Foo();
$testcase->example = 'Dynamic property';
echo $testcase->example;
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X