In the framework development, modular development and other occasions, we may have a requirement, that is, the PHP runtime to instantiate the object dynamically.
What is a dynamic instantiation of an object? Let's take a look at the concept of a variable function (variable function) in PHP, such as the following code:
function foo () { echo ' This is the Foo function ';} $bar = ' foo '; $bar ();
Running the above code will output "This is the Foo function". For details, refer to the PHP Manual: mutable functions. Of course, if you need to invoke it dynamically, then use the Call_user_func or Call_user_func_array function. The use of these two functions is not the focus of this article, do not understand the students please consult other information. Back to the topic of this article: what is a dynamic instantiation of an object? I think the object is instantiated dynamically, that is, the object that needs to be instantiated is the object that needs to be instantiated (determined by the variable) at the time of the program run (run-time), rather than simply writing it to die in the code.
From the above example, we already know how to invoke a function dynamically at runtime, and now, in some code, we need to dynamically instantiate a class, what should we do?
Case one: The constructor of the class has no arguments or the number of arguments is determined
If the constructor of a class has no arguments, or if the class we are instantiating does not have a constructor at all, it seems a little simpler to change it, according to the example above, uh, divert, who wouldn't:
code example: (constructor without parameters)
Class FOO { private $a, $b; Public Function construct () { $this->a = 1; $this->b = 2; } Public Function test () { echo ' This is the method test of Class foo<br/> '; Echo ' $this->a= ', $this->a, ', $this->b= ', $this->b; }} $bar = ' FOO '; $foo = new $bar (); $foo->test ();
Run it and see the output as follows:
This is the method test of Class foo$this->a=1, $this->b=2
Well, if we're going to pass the argument, then that's it:
Class FOO { private $a, $b; Public function construct ($a, $b) { $this->a = $a; $this->b = $b; } Public Function test () { echo ' This is the method test of Class foo<br/> '; Echo ' $this->a= ', $this->a, ', $this->b= ', $this->b; }} $bar = ' FOO '; $foo = new $bar (' Test ', 5); $foo->test ();
Similar results can be obtained:
This is the method test of Class Foo$this->a=test, $this->b=5
It's ideal.
Case two: The parameter number of the constructor of the class is indeterminate
This situation is going to be a lot of trouble, but if you want to write more generic, you have to consider this situation. For example, we have the following two classes
class Foo {public function test () { echo ' This is the method test of Class Foo '; }} Class BAR { private $a, $b; Public function construct ($a, $b) { $this->a = $a; $this->b = $b; } Public Function test () { echo ' This is the method test of Class bar<br/> '; Echo ' $this->a= ', $this->a, ', $this->b= ', $this->b; }}
We want a generic way to instantiate these two classes. We notice that the Foo class does not write a constructor, or that the constructor of the Foo class has zero arguments, whereas the bar class constructor has parameters. Fortunately, PHP5 is strong enough to introduce the concept of reflection, please refer to the PHP Manual: Reflection, although the manual also has nothing to refer to:). Fortunately, the name is written well, from the class name and method name above can be seen from the general clue, do not need too much text.
Well, let's start this thing with PHP5 reflexes:
(still with PHP4 's classmate please do not walk away, if you have a non-reflective version of PHP or you do not want to be compatible or upgrade, anyway, do not want to use reflection, the following solutions)
$class = new Reflectionclass (' FOO '); $foo = $class->newinstance (); or $foo = $class->newinstanceargs (); $foo->test ();
Did you see anything? Then come:
$class = new Reflectionclass (' BAR '), $bar = $class->newinstanceargs (Array (), $bar->test ();
OK, it seems to be okay, then tidy it up, a general function, we want to design, the first function of this function is to instantiate the class name, starting from the second argument is to instantiate the class constructor parameters, there are a few to write a few up, do not write. To implement functions with variable number of arguments, we have two methods:
The first type is similar to:
function foo ($arg 1, $arg 2 = 123, $arg 3 = ' Test ', $arg 4 = null, ...) { //some code;}
Approach, this method has two shortcomings, the first one is if you need to pass 100 parameters to write 100 parameters? The second is that you have to decide in the program which parameters are not NULL, or other default values. (Aside from this: the default value for this notation must be at the end, you cannot insert a parameter without a default value in the middle or in front of the default value, otherwise you must explicitly write the value of the default value parameter when you call)
Another way to implement a variable number of parameters is to use PHP's built-in function Func_get_args (click here to see the manual) to get the arguments passed to the function. Similar functions have func_get_num and func_get_arg, forget it, I'm lazy, you find the manual to see it.
So, it seems to be a lot easier to use this function, according to the arrangement of the imaginary function parameters, the code should look like this:
function newinstance () { $arguments = Func_get_args (); $className = Array_shift ($arguments); $class = new Reflectionclass ($className); Return $class->newinstanceargs ($arguments);}
OK, let's take a look at the effect:
$foo = newinstance (' foo '); $foo->test ();//Output Result://this is the method test of Class Foo$bar = newinstance (' Bar ', 3, 5); $ba R->test ();//Output Result://this is the method test of Class bar//$this->a=3, $this->b=5
Just four lines of code, the effect is quite perfect ah. So, if applied to the class, we can use this idea, directly written magic method, can make our class more cool Oh!
Class INSTANCE { function call ($className, $arguments) { $class = new Reflectionclass ($className); Return $class->newinstanceargs ($arguments);} } $inst = new INSTANCE (); $foo = $inst->foo (); $foo->test ();//Output Result://this is the method test of Class Foo$bar = $inst-&G T;bar (' arg1 ', ' arg2 '); $bar->test ();//output://this is the method test of Class bar//$this->a=3, $this->b=5
A click.
Next, consider the case where the reflection class is not used. For example, there is no reflection in PHP4, and some old projects run on PHP4. Or to ensure that the project to the unknown environment compatibility, Whatever, to care about how the dynamic transfer of the reference bar. There is only one function for dynamic parameters in PHP: Call_user_func_array (click here to view the manual). This is a function that dynamically invokes a function that can pass a function's arguments as an array to the function to be called. Well, I've been dizzy myself, and I'll look directly at the example:
function foo ($a, $b) { echo ' $a = ', $a, ' <br/> '; echo ' $b = ', $b;} Call_user_func_array (' foo ', array (1, ' string '));//The output of this example://$a =1//$b =string
So, to implement this method to dynamically instantiate the object and to pass the parameters, uh ..., only the curve to the salvation, we have to write a function, let the function to instantiate the object, and the function of the parameters of the functions of the object to instantiate the constructor of the class is just fine. Stop! So how many parameters does this function have? How to implement different number of parameters to pass? Hey, I was a sneer, you forgot to provide a function in PHP to create an anonymous function? (It's starting to wrap up again ...) Create_function (manual here), according to the example of the manual can be drawn directly, I do not bother to type, directly look at the following code, comments I write clearly, we all understand:
function Newinst () { //Get all parameters $arguments = Func_get_args (); pops up the first argument, which is the class name, and all that is left is the argument to the constructor of the instantiated class $className = Array_shift ($arguments); Add a prefix to all parameter key values $keys = Array_keys ($arguments); Array_walk ($keys, Create_function (' & $value, $key, $prefix ', ' $value = $prefix. $value; '), ' $arg _ '); The function of dynamically constructing instantiated classes is mainly the number of dynamically constructed parameters $paramStr = Implode (', ', $keys); $newClass =create_function ($PARAMSTR, "return new {$className} ({$paramStr});"); Instantiates the object and returns the return Call_user_func_array ($newClass, $arguments);}
Well, as to the effect is what, on the trouble you crossing yourself to move, run a look, is not the result of their own expectations.
If you rewrite the Magic method inside the class, hum, power, you know! Then, I'm still lazy, if you want to write a magic method, I believe that easy things you can easily do. Just be a homework. In addition, the code of this article is I ran, but, when writing the article did not use the Copy/Paste function, so you'd better not copy and paste. If you copy down from the code in this article to run an error, but also ask you to debug yourself, programming is not to write it yourself.
It was supposed to end here, but I thought about the method I used before I thought about it. ), with the emphasis on the exchange of attitude, together put out. My example is two key functions: Extract and Eval. But I personally think that using the Eval function to compare the cottage, can not use the best. Then came up with the above method, haha, programming is the most important idea, is not it? OK, another homework question, you can try these two functions (and, of course, use other functions) to implement a function with an indefinite number of parameters to instantiate the object dynamically.