Put an onion _php the pig's nose

Source: Internet
Author: User
Keywords Prototype call Object Object pro
PHP has some characteristics of dynamic language, but not completely. Although the logo of PHP is an elephant, the nose of this elephant is too short to be able to reach something often, but it is like a pig. The purpose of this paper is to explore a method of making PHP more dynamic, mainly simulating the prototype inheritance of Javascript. Since it is a simulation, it is not really able to make PHP dynamic, just plug in an onion, let it be more "like" a point.

I. Basic Operations
By dynamically adding properties to an object through Javascript's prototype, we can:
Object.prototype.greeting = ' Hello ' var o = new Objectalert (o.greeting)

JS built-in object can be regarded as a "class", any Js "class" has prototype built-in objects, using PHP to simulate it can be:
Error_reporting (e_all); class object{public     static $prototype;     protected function __get ($var) {         if (Isset (self:: $prototype, $var)) {             return self:: $prototype, $var;}}

Then we can:
Object:: $prototype->greeting = ' Hello '; $o = new Object;echo $o->greeting; Output Hello

This takes advantage of the automatic transformation features of PHP. In PHP, we want to declare an array, do not need to $var = Array () and then do $var [] = some_value, use the latter directly to get an array; Similarly, the $object is automatically defined as the StdClass object when the->var is directly $object. This solves the problem of not declaring public static $prototype = new StdClass when defining static properties within a class.

Add a method to the "class" Dynamically in Js:
Object.prototype.say = function (word) {alert (word)}o.say (' Hi ')

Simulate in PHP:
Error_reporting (e_all); class object{public     static $prototype;     protected function __get ($var) {         if (Isset (self:: $prototype, $var)) {             return self:: $prototype, $var;}}     protected function __call ($call, $params) {         if (Isset (self:: $prototype, $call) && is_callable ( Self:: $prototype-$call) {             return Call_user_func_array (self:: $prototype, $call, $params);}         else {             throw new Exception (' Call to undefined method: '. __class__. ":: $call ()"); }}}

This way, you can
Object:: $prototype->say = create_function (' $word ', ' echo $word; '); $o->say (' Hi ');

But the result of PHP create_function return is not the same as the function object in JS, JS function object is a kind of closure (closure), it can directly call the host's properties, such as
Object.prototype.rock = function () {alert (this.oops)}o.oops = ' oops ' O.rock ()

But in PHP, we can't write.
Object:: $prototype->rock = create_function (' ', ' echo $this->oops; '); $o->oops = ' oops '; $o->rock ();

The Fatal error:using $this is reported as not in object context because create_function returns an anonymous normal function that does not have a host. To solve this problem, we need to pass in the object itself in the argument, and we cannot use the $this variable name to do the argument, we temporarily use a $caller variable name:
Object:: $prototype->rock = create_function (' $caller ', ' echo $caller->oops; '); $o->oops = ' oops '; $o->rock ($o);

Now it's all right, but it looks weird and doesn't look like a dynamic language at all. Well, this onion is still a little short, still not "elephant".

Here's the problem:
1. What kind of object-oriented is it to pass the object itself when invoking a dynamic method?
2. We want to use $this in our code, which is just like being object-oriented.

Workaround:
1. Re-write a function instead of create_function, squeeze a parameter in the parameter section $that go in as the first parameter, in __call to the anonymous function when passing parameters to the object itself $this as the first parameter.
2. Allow $this to be used in code, we replace $this with $that in the substitution function.

We'll add a create_method function to it instead of create_function.
function Create_method ($args, $code) {     if (Preg_match ('/\ $that \b/', $args)) {         throw new Exception (' Using reserv ed word \ ' $that \ ' as argument '); }     $args = Preg_match ('/^\s*$/s ', $args)? ' $that ': ' $that, '. $args;     $code = Preg_replace ('/\ $this \b/', ' $that ', $code);     Return Create_function ($args, $code); }

$that as a "reserved word" in the parameter, an exception will be thrown when it appears in the Parameters section. (In the early night version of PHP5, $that was also a reserved word)

Accordingly, the __call in Object must also be changed
Class object{public     static $prototype;     protected function __get ($var) {         if (Isset (self:: $prototype, $var)) {             return self:: $prototype, $var;}}     protected function __call ($call, $params) {         if (Isset (self:: $prototype, $call) && is_callable ( Self:: $prototype $call)) {             array_unshift ($params, $this);//here!             Return Call_user_func_array (self:: $prototype, $call, $params); }         else {             throw new Exception (' Call to undefined method: '. __class__. ":: $call ()"); }}}

Now, we can
Object:: $prototype->rock = Create_method (' ', ' echo $this->oops; '); $o->oops = ' oops '; $o->rock ();





two. Inheritance
One of the main characteristics of object-oriented is inheritance, which preserves the ability to maximize code reuse. However, if you use the Object class of the example above to create an inheriting class, you will get an error because
1. Static properties inherited by subclasses $prototype always belong to the parent class (regardless of whether the $prototype is scalar or a list, the object is not said)
2. If the subclass inherits from a method that has the Self keyword, self points to the parent class, not the child class
Class object{public     static $prototype;     protected function __get ($var) {         ...}     protected function __call ($call, $params) {         ...}} Class Test extends Object{}test:: $prototype->greeting = ' Hello ';p rint_r (Object:: $prototype);/* Outputsstdclass Object (    [Greeting] = Hello) */test:: $prototype->say = Create_method (' $word ', ' echo $word; '); $o = new Object; $o->say (' Hi ');/* outputshi*/
  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.