A very efficient way of instantiating a class dynamically in PHP

Since PHP is a loosely typed language, it provides great flexibility in creating variables and objects at runtime without having to specifically declare them first. It is well known that $i=10, $i=”test”, $i = date() will all work without creating any syntax or compile errors.

A lesser used concept is that this feature can be used to create an object at runtime without having to check for the object type at first. Eg.if you have had 3 classes and only one of them had to be created depending on a condition the following would be the sample code:

<?php
	error_reporting(E_ALL);

	class Generic {
		function xprint() {
			echo("generic");
		}
	}
	class A extends Generic{
		function xprint() {
			echo("A");
		}
	}

	class B extends Generic{
		function xprint() {
			echo ("B");
		}
	}

	class C extends Generic{
		function xprint() {
			echo("C");
		}
	}


	$test = "B";
	if ($test =="B")
		$x = new B();
	else if ($test == "A"
		$x = new A();
    else if ($test == "C")
	    $x = new C();
	$x->xprint();
	echo("end");
?>

Instead of doing multiple checks and then creating the relevant class, a more efficient way is to pass the classname as a string and then create it directly as shown below:

<?php
	error_reporting(E_ALL);

	class Generic {
		function xprint() {
			echo("generic");
		}
	}
	class A extends Generic{
		function xprint() {
			echo("A");
		}
	}

	class B extends Generic{
		function xprint() {
			echo ("B");
		}
	}

	class C extends Generic{
		function xprint() {
			echo("C");
		}
	}


	$test = "B";
	$x = new $test();
	$x->xprint();
	echo("end");
?>

The above code will print “B” since it creates the class B in $x. What about classes where arguments are required in the constructor? Simple call it with the arguments eg. $x = new $test(“arg1”, “arg2”);

8 Comments

  1. This works well, but you have to be sure to put tight controls on the variable used to define the instantiated class. If you don’t, the user could instantiate arbitrary classes. If you have auto load enabled, the problem scales. If your autoloader is more advanced and turns underscores into slashes like Zend Framework, you open yourself up to directory traversal exploits as well.

    Always always always sanitize a variable used to dynamically instantiate a class.

  2. Good post – I also agree with the security considerations Ian posted.

    This could be considered another implementation of the variable variable paradigm in PHP (I was just talking to a colleague about this today).

    For another blog entry, you could show this in practical format using a Factory design pattern. How about something like this:
    – create static factory method with $className parameter
    – factory method uses class_exists() to determine if the $className exists
    – if so, returns new $className

    • @Aaron The Factory design pattern is a good approach. Actually the cases where one would use this way of instantiating is limited. 99% of the time, it still makes sense to call a class the standard way.

      Only when you have to instantiate one among several classes and you are not sure which class its going to be then this kind of shortcut saves coding effort. The objective was to save a whole series of if-then-else conditions.

    • I have class like
      Class Testing {
      private $test;
      private $test1

      public function __construct(\Sample\test $test,\Sample\test1 $test1)
      }
      And I have array [‘Testing’,’\Sample\test’,’\Sample\test1′]

      How I can create object for this dynamically

  3. Hi

    I have class like

    Class Testing {
    private $test;
    private $test1

    public function __construct(\Sample\test $test,\Sample\test1 $test1)
    }
    And I have array
    [‘Testing’,’\Sample\test’,’\Sample\test1′]

    How I can create object for this dynamically

2 Trackbacks / Pingbacks

  1. abcphp.com
  2. สร้าง dynamic object แบบ runtime | jQuery, Ajax, PHP, JSON, XML, Web Technologies

Leave a Reply to Aaron Saray Cancel reply

Your email address will not be published.


*