Php implements a simple chained operation, and php implements chained operations.
I recently read the book "php core technology and best practices". The first chapter of the book mentions that the _ call () method can be used to implement a simple string chain operation. For example, the following Operation filters the string and then calculates the length, which is generally written as follows:
strlen(trim($str));
Can the following statement be implemented?
$str->trim()->strlen();
Next, let's try it out.
To put it bluntly, chained operation is actually the method of calling objects. To implement a string chain operation, we need to implement a string class and then call the object of this class. My expectations for the string class are as follows: (1) When I create an object, I can assign a value to the attribute of the object and access the attribute to read the value. (2) I can call the trim () and strlen () methods; (3) I can also call the method $ str-> trim ()-> strlen ().
The above (1) is the basic requirement of a string class. First, we implemented the following:
1 class String2 {3 public $value;4 5 public function __construct($str=null)6 {7 $this->value = $str;8 }9 }
Try:
1 $str = new String('01389');2 echo $str->value;
Then, let's look at the Second 2nd items. First, we realized $ str-> trim (). The idea in the reference book is to trigger the _ call method and then execute call_user_func. The Code is as follows:
1 class String 2 { 3 public $value; 4 5 public function __construct($str=null) 6 { 7 $this->value = $str; 8 } 9 10 public function __call($name, $args)11 {12 $this->value = call_user_func($name, $this->value, $args[0]);13 return $this;14 }15 }
Test:
1 $str = new String('01389');2 echo $str->trim('0')->value;
The result is as follows:
The above lines need to be noted: $ this-> value = call_user_func ($ name, $ this-> value, $ args [0]); $ name is the name (trim) of the callback function. The next two are the parameters of the callback function (tirm). Do not reverse the order of parameters. $ Args is an array.
Strlen () must be implemented in the first line. In this case, the 2nd line in the code above is critical: return $ this; its function is to call trim () in the second line () after the string is processed, the value attribute is assigned again, and then the reference of the current object is returned. In this way, other methods in the object can perform continuous operations on the attribute value, thus implementing the chain operation. $ Str-> strlen () is implemented as follows:
1 class String 2 { 3 public $value; 4 5 public function __construct($str=null) 6 { 7 $this->value = $str; 8 } 9 10 public function __call($name, $args)11 {12 $this->value = call_user_func($name, $this->value, $args[0]);13 return $this;14 }15 16 public function strlen()17 {18 return strlen($this->value);19 }20 }
Test:
1 $str = new String('01389');2 echo $str->strlen();
Result:
Chain Operation:
echo $str->trim('0')->strlen();
Result:
This article should have ended. However, if I think about it, the _ call () method can also be used to implement chained operations. The following is the implementation of do not use _ call:
1 class String 2 { 3 public $value; 4 5 public function __construct($str=null) 6 { 7 $this->value = $str; 8 } 9 10 public function trim($t)11 {12 $this->value = trim($this->value, $t);13 return $this;14 }15 16 public function strlen()17 {18 return strlen($this->value);19 }20 }
The key to chained operation is to return $ this after completing the operation.
In addition, inspired by this article in the garden, this article replaces call_user_func_array () with call_user_func (), and modifies the _ call () method as follows.
1 public function __call($name, $args)2 {3 array_unshift($args, $this->value);4 $this->value = call_user_func_array($name, $args);5 return $this;6 }
The effect of the above _ call () method is the same, so the Code seems more elegant than the previous implementation.
Summary:
_ Call () is triggered when an object calls an inaccessible method. Therefore, you can create a dynamic method of the class and implement the php method overload function, but it is actually a syntactic sugar (_ construct () method ).
If there is no syntax sugar such as _ call (), can we create dynamic methods and perform chained operations? I think it will involve the following issues: whether the class method exists and can be called, which can be implemented using methods such as method_exists, is_callable, and get_class_methods. In addition, it is to assign a value (initialization) to the attribute when creating an object. This syntactic sugar is really convenient, but it is not necessary. Wait until you have time to study.