0

Basically my setup is that I have a lot of objects that I want to create. What type of object it will become is dependent on one variable, which is the type. So originally I would have to do many if statements, so to shorten it I created an array, but I am running in to the problem of being able to create the actual object through the array.

Here is what I had originally:

if($object->type = 'text')
{
    $object_new = new Text();
} elseif($object->type = 'image') {
    $object_new = new Image();
} ....

But what I wanted to do is:

$all_objects = array('text'=> new Text(), 'image' => new Image(), ...);
$object_new = $all_objects($object->type);

Which would shorten my code by a lot as well as make it more efficient.

gen_Eric
  • 223,194
  • 41
  • 299
  • 337
user1399078
  • 167
  • 2
  • 4
  • 8

3 Answers3

2

If there is no further dependencies to these object, you can simply do

$className = $object->type;
$instance = new $className;

If you need more sophisticated creation logic, you can put the creation code in Lambdas and call those then, e.g.

$allTypes = array(
    'text' => function($string) { return new Text($string); },
    'Image' => function($path) { return new Image($path); }
);
$instance = call_user_func_array($allTypes[$object->type], array($argument1));

Or you create a Factory object and put a switch/case into it:

class Factory
{
    public function create($type)
    {
        switch ($type)
        {
            case 'text':
                return new Text;
            case 'image':
                return Image($this->create('foo'));
            case 'foo':
                return new Foo;
            default:
                throw new Exception('No clue what to create');
        }
    }
}

Also checkout Is there a call_user_func() equivalent to create a new class instance?

Community
  • 1
  • 1
Gordon
  • 312,688
  • 75
  • 539
  • 559
  • Heck, you can even just do `$instance = new $object->type;`. – gen_Eric May 16 '12 at 16:13
  • One needs to be carefull though, using this with *__autoload*-ing and case-sensitive filesystems. (at least for the first method ;)) – Yoshi May 16 '12 at 16:15
0

Making an array of $all_objects will cause more problems. When you get an element from there, it would be a reference, so each time you accessed an element, it'd be the same as the last time you accessed it. (example: http://codepad.org/Z4B7glk9)

Instead try something like this (Class names in PHP are case insensitive):

$object_new = new $object->type();

DEMO: http://codepad.org/Hq09jkHz

gen_Eric
  • 223,194
  • 41
  • 299
  • 337
0

This might be what you're looking for:

$types = array('image', 'text', 'link', 'somethingelse');
foreach ($types as $type) {
    $$type = new ucfirst($type);
}

This means:

$image         = new Image;
$text          = new Text;
$link          = new Link;
$somethingelse = new Somethingelse;

Of course, you need to have Image, Text, Link and Somethingelse classes.

Samy Dindane
  • 17,900
  • 3
  • 40
  • 50
  • I think he just wants to make an instance of a class using a string as the name. I don't think he needs to make instances of all of the classes. – gen_Eric May 16 '12 at 16:11