0%

转 如何在PHP中实现链式方法调用

写程序的人都喜欢偷懒,希望少打几行代码,并且让代码看起来很酷。
所以很多人写程序都会选择三元运算取代if..else…。
而用过JS的人应该都见识过js中的链式方法。

如 somevars.func().func2().func3()…funcN();
这样的写法使得代码更简练,并且作用关系一目了然。
那么在php中可以这么做么,显然也是可以的,但是php与js的差别是,在js中变量本身具有对象的性质,但是php的变量却不是。
所以解决方法就是让php的变量变成一个对象。
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<?php 
error_reporting(E_ALL | E_STRICT);
/**
* PHP-OOP_VAR 让php的变量变成一个对象
*
*
* @version 0.0.1
* @author momodev
* @website http://momodev.blog.51cto.com
* @license GPL v3 - http://vork.us/go/mvz5
*/
Abstract Class Base_OOP_VAR{

/**
* 追溯数据,用来进行调试
* @var array
*/
private $_trace_data = array();

/**
* 保存可用的方法列表
* @var array
*/
protected $_methods = array(
);

/**
* 数据本身
* @var null
*/
protected $data;

/**
* 初始化变量
* @param var
* @return void
*/
public function __construct($data){
$this->data = $data;
$this->_trace_data['__construct'] = $data;
return $this->data;
}

/**
* 魔术方法,当试图对对象进行打印如 echo 或print的时候,调用这个方法
*
* 比如:
* $a = new stdClass;
* echo $a;
* 等价于 echo $a->__toString();
*
* @return $data
*/
public function __toString(){
if(is_int($this->data) || is_float($this->data))
$this->data = (string)$this->data;
return $this->data;
}

/**
* 魔术方法,当试图调用一个不存在的方法时,这个函数会接管这个请求
*
* 比如
* $a= new stdClass;
* $a->output();
* 等价于
* $a->__call("output");
*
* @return object
*/
public function __call($name,$args){
$this->vaild_func($name);
if(!$args) $args = $this->data;
$this->data = call_user_func($name,$args);
$this->_trace_data[$name] = $this->data;
return $this;
}

/**
* 检查方法是否是有效的
* @params string $name
* @return void
*/
private function vaild_func($name){
if(!in_array($name,$this->_methods)){
throw new Exception("invaild method");
}
}

/**
* 对数据进行追溯
* 比如
* $a = new String(" Hello World");
* $a->trim()->strlen();
* 在调用trim的时候,实际上把前后的空格给去掉了,所以数据是
* Hello World
* 在调用strlen的时候
* 得到了一个字符串长度的值
* 追溯数据方便检查在哪个环节数据出现了问题
*
* @return string
*/
public function trace(){
echo "<pre>";
var_dump($this->_trace_data);
echo "

“;
}

}

/**

  • ex. 怎么来使用这个抽象类
  • 声明一个字符串对象
  • class String extends Base_OOP_VAR{
  • //添加可用的方法
  • protected $_methods = array(
  •  'trim', 
    
  •  'strlen', 
    
  •  'gettype' 
    
  • );
  • }
  • //使用这个对象
  • $a = new String(“ Hello world”);
  • echo $a->trim()->strlen()->gettype();
  • $a->trace();
  • //调试的数据类似这样
  • array(4) {
  •  //初始化时的数据 
    
  •  ["__construct"]=> string(12) " Hello world" 
    
  •  //去除前后空格的数据  
    
  •  ["trim"]=> string(11) "Hello world" 
    
  •  //代表字符串长度的数据  
    
  •  ["strlen"]=> int(11)  
    
  •  //代表字符串类型的数据 
    
  •  ["gettype"]=> string(7) "integer" 
    
  • }
  • */

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!