Dynamically create PHP object based on string

I would like to create an object in PHP based on a type defined by a string in a MySQL database. The database table has columns and sample data of:

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

...with PHP data types

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

Using only one query, I would like to SELECT a row by id and create an object of the type define the table's type column with other columns in the SELECTed row being assigned to the newly created object.

I was thinking that using:

  1. mysql_fetch_object()
  2. Reading the type attribute
  3. Creating an object with type defined by type attribute

But know of no way to dynamically create a type based on a string. How does one do this?

Answers


But know of no way to dynamically create a type based on a string. How does one do this?

You can do it quite easily and naturally:

$type = 'myclass';

$instance = new $type;

If your query is returning an associative array, you can assign properties using similar syntax:

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

There's a very neat syntax you can use that I learned about a couple of months ago that does not rely on a temporary variable. Here's an example where I use a POST variable to load a specific class:

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

In your specific case though, you would be able to solve it by using PDO. It has a fetch mode that allows the first column's value to be the class the row instantiates into.

$sth->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE);

$instance = new $classname; // i.e. $type in your case

Works very well...


as silkfire says, this can be achieved by using PDO specific modes, so here is an example. Using your same database values and defined objects:

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

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

with a single query (you must name the field containing the class name first):

$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

this is cool but it gets cooler with a while

$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

you can define a constructor (which will be called after the values from database are assigned to properties) to work on those dynamically assigned properties, say by replacing a string with it's uppercased value

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

Below is what I was looking for when I came to this thread. use {"objectName"} (brackets) to declare or reference the object name in the form of a string.

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

This way of referring to the object seems to be interchangeable. I couldn't find the answer so i had to fool around with it Until I found a way.


Need Your Help

"undefined reference to" errors when linking static C library with C++ code

c++ c static-libraries

I have a test file (just for the link test) where I overload the new/delete operators with my own malloc/free library called libxmalloc.a. But I keep getting "undefined reference to" error as follo...

Is file empty check

c#

How do I check if a file is empty in C#?