web-dev-qa-db-fra.com

Créer dynamiquement PHP objet basé sur une chaîne

J'aimerais créer un objet dans PHP en fonction d'un type défini par une chaîne dans une base de données MySQL. La table de base de données a des colonnes et des exemples de données de:

 id | type | propertyVal
----+------+-------------
  1 | foo  | lorum
  2 | bar  | ipsum

... avec PHP types de données

class ParentClass {...}
class Foo extends ParentClass {private $id, $propertyVal; ...}
class Bar extends ParentClass {private $id, $propertyVal; ...} 
//...(more classes)...

En utilisant une seule requête, je voudrais sélectionner une ligne par identifiant et créer un objet du type, définir la colonne de type de la table avec les autres colonnes de la ligne SELECTed affectées au nouvel objet créé.

Je pensais qu'en utilisant:

  1. mysql_fetch_object()
  2. Lecture de l'attribut type
  3. Création d'un objet avec le type défini par l'attribut type

Mais je ne connais aucun moyen de créer dynamiquement un type basé sur une chaîne. Comment est-que quelqu'un peut faire ça?

44
Mat Kelly

Mais je ne connais aucun moyen de créer dynamiquement un type basé sur une chaîne. Comment est-que quelqu'un peut faire ça? 

Vous pouvez le faire assez facilement et naturellement:

$type = 'myclass';

$instance = new $type;

Si votre requête renvoie un tableau associatif, vous pouvez affecter des propriétés en utilisant une syntaxe similaire:

// build object
$type = $row['type'];
$instance = new $type;

// remove 'type' so we don't set $instance->type = 'foo' or 'bar'
unset($row['type']);  

// assign properties
foreach ($row as $property => $value) {
   $instance->$property = $value;
}
100
meagar

Vous pouvez utiliser une syntaxe très soignée que j'ai apprise il y a quelques mois et qui ne repose pas sur une variable temporaire. Voici un exemple où j'utilise une variable POST pour charger une classe spécifique:

$eb = new ${!${''} = $_POST['entity'] . 'Binding'}();

Cependant, dans votre cas particulier, vous seriez capable de le résoudre en utilisant PDO. Il a un mode de récupération qui permet à la valeur de la première colonne d'être la classe dans laquelle la ligne est instanciée.

$sth->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE);
7
silkfire
$instance = new $classname; // i.e. $type in your case

Fonctionne très bien ...

7
roman

Voici ce que je cherchais quand je suis arrivé à ce fil. utilisez {"objectName"} (crochets) pour déclarer ou référencer le nom de l'objet sous la forme d'une chaîne.

$gameData = new stdClass();
$gameData->location = new stdClass();
$basementstring = "basement";

class tLocation {
    public $description;
}

$gameData->location->{'darkHouse'} = new tLocation;
$gameData->location->{"darkHouse"}->description = "You walkinto a dusty old house";


$gameData->location->{$basementstring} = new tLocation;
$gameData->location->{"basement"}->description = "its really damp down here.";

//var_dump($gameData); 
echo $gameData->location->basement->description;

Cette façon de faire référence à l'objet semble être interchangeable. Je ne pouvais pas trouver la réponse, je devais donc batifoler avec elle jusqu'à ce que je trouve un moyen.

0
Peter S McIntyre

comme le dit silkfire, cela peut être réalisé en utilisant des modes spécifiques au PDO, voici donc un exemple. En utilisant vos mêmes valeurs de base de données et objets définis:

 id | type | propertyVal 
---- + ------ + -------------
 1 | foo | lorum 
 2 | bar | ipsum 

 class ParentClass {...} 
 class Foo étend ParentClass {private $ id, $ propertyVal; ...} 
 class Bar étend la classe ParentClass {private $ id, $ propertyVal; ...} 
 // ... (plus de classes) ...

avec une seule requête (vous devez d'abord nommer le champ contenant le nom de la classe):

$stmt = $db->prepare('SELECT type,id,propertyVal FROM table WHERE id=1');
$stmt->execute();
$foo = $stmt->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE);
var_dump($foo); // $foo is a newly created object of class foo, with properties named like and containing the value of subsequent fields

c'est cool mais il fait plus froid avec un certain temps

$stmt = $db->prepare('SELECT type,id,propertyVal FROM table');
$stmt->execute();
while ($object = $stmt->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE))
 {var_dump($object);} // here all desired objects, dynamically constructed accordingly to the first column returned by the query

vous pouvez définir un constructeur (qui sera appelé après que les valeurs de la base de données ont été affectées à des propriétés) pour travailler sur ces propriétés affectées dynamiquement, par exemple en remplaçant une chaîne par sa valeur en majuscule

class foo
 {function __construct ()
   {$this->uper = strtoupper($this->propertyVal);}}
0