用php实现一个简单的链式操作

最近在读《php核心技术与最佳实践》这本书,书中第一章提到用__call()方法可以实现一个简单的字符串链式操作,比如,下面这个过滤字符串然后再求长度的操作,一般要这么写:

strlen(trim($str));

那么能否实现下面这种写法呢?

$str->trim()->strlen();

下面就来试下。

链式操作,说白了其实就是链式的调用对象的方法。既然要实现字符串的链式操作,那么就要实现一个字符串类,然后对这个类的对象进行调用操作。我对字符串类的期望如下:(1)当我创建对象时,我可以将字符串赋值给对象的属性,并且可以访问这个属性读取值;(2)我可以调用trim() 和strlen()方法;(3)我还可以这么调用方法$str->trim()->strlen()。

上面的第(1)条,是一个字符串类的基本要求。先把这个实现了:

1 class String
2 {
3     public $value;
4
5     public function __construct($str=null)
6     {
7         $this->value = $str;
8     }
9 }

可以试下:

1 $str = new String(‘01389‘);
2 echo $str->value;

然后再看第2条,先把$str->trim()实现了,参考书中的思路:触发__call方法然后执行call_user_func。代码如下:

 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 }

测试下:

1 $str = new String(‘01389‘);
2 echo $str->trim(‘0‘)->value;

结果如下:

上面需要注意的是第12行: $this->value = call_user_func($name, $this->value, $args[0]); $name是回调函数的名字(这里也就是trim),后面两个是回调函数(tirm)的参数,参数的顺序不要弄颠倒了。$args是数组,也需要注意下。

第2条中还要实现strlen(),这时上面代码中的第13行就很关键了: return $this; 它的作用就是,在第12行调用trim()处理完字符串后重新value属性赋值,然后返回当前对象的引用,这样对象内的其他方法实现对属性value的连续操作了,也就实现了链式操作。$str->strlen()实现如下:

 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 }

测试下:

1 $str = new String(‘01389‘);
2 echo $str->strlen();

结果:

链式操作:

echo $str->trim(‘0‘)->strlen();

结果:



到这里,这篇文章本该就结束了。但是,我想了下,其实不用__call()方法,也是可以实现链式操作的。下面是不用__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 }

链式操作的关键是在做完操作后要return $this。

另外,本文受到园子里这篇文章的启发,用call_user_func_array()替换了call_user_func()实现,将__call()方法修改如下。

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     }

与上面的__call()方法效果是相同的,这样代码似乎比之前的实现要优雅些。



总结:

__call()在对象调用一个不可访问的方法时会被触发,所以可以实现类的动态方法的创建,实现php的方法重载功能,但它其实是一个语法糖(__construct()方法也是)。

那么如果没有__call()等语法糖,能否实现动态方法的创建和链式操作呢?我想会涉及到以下几个方面的问题:类方法是否存在和可以调用,这个可以用method_exists、is_callable、get_class_methods等方法来实现,另外,就是在创建对象时给属性赋值(初始化),这个语法糖确实方便,不过不是必需的。等有时间再研究下吧。

时间: 2024-10-03 22:53:22

用php实现一个简单的链式操作的相关文章

js实现一个简单的链式操作

如何实现一个链式操作 function person() {} person.prototype = { setname: function(name) { this.name = name return this }, setage: function(age) { this.age = age return this }, getinfor: function() { console.log(this.age) console.log(this.name) } } var person1 =

js简单实现链式调用

链式调用实现原理:对象中的方法执行后返回对象自身即可以实现链式操作.说白了就是每一次调用方法返回的是同一个对象才可以链式调用. js简单实现链式调用demo Object.prototype.show = function() {   console.log('show');   return this;  }  Object.prototype.hide = function() {   console.log('hide');   return this;  }  var div = doc

Javascript、C#、php、asp、python 等语言的链式操作的实现

一.什么是链式操作 把需要的下一步操作的对象通过上一步操作返回回来.使完成某些功能具有持续性. 二.链式操作优点 代码更精简优雅.链式操作能大大精简代码量,多项操作一行代码一气呵成,搞定: 链式操作应用场景除了想前端jquery方面的操作dom,后端web框架,在开发orm相关的框架也是常常用到 三.各种语言的链式操作实现 以下根据简单的实现数据库查询的类似实现一些web框架的 orm.查询类的各种DEMO 1.javascript 的链式操作大家最熟悉不过了,jquery 的整个框架就是链式操

PHP链式操作输出excel(csv)

工作中经常会遇到产品运营让导出一些简单的比较规范的数据,这时候要是有一个简单的方法可以用就简单多了.下面是我的一个输出简单的excel(csv)的方法类,用到了链式操作.说到链式操作,在jquery中可能经常用到,是不是也感觉到链式操作用起来很爽,我们也在这个类中实现下链式操作. 其实链式操作很简单的,就是在前一个类方法最后返回一个该类的对象($this),提供给下一个方法调用. <?php class Array2csv{ /* *@var string $ext 扩展名 */ private

PHP链式操作的实现--即PHP数据操作类。

所谓链式操作最简单的理解就是 操作完毕之后再返回对象$this 想必大家工作中基本都快用烂了得东西. 下面就是一个链式操作MYSQL数据库类. 最常见的链式操作 每一个方法操作之后,返回一个对象,直到最后一个方法才是执行和返回整个链式操作的结果. $model->where()->field()->limit()->select() use PDO; class CyDB extends PDO { private $config = null; public $table; //

简述jQuery的链式操作

首先,两个问题: JQuery的链式操作是如何实现的? 为什么要用链式操作? 怎样使用链式操作? 原理百度上面一大把,我也不能很好的解释,不过它的用法很简单: 关键就在于对象里的方法有:return this.这就是说调用了方法之后把对象给返回了回来,不就可以继续调用方法了吗?所以链式操作就这样实现了.举个栗子: //定义一个类 function Obj(){} //扩展它的原型 Obj.prototype = { setName:function(name){ this.name = name

jQuery链式操作[转]

用过jQuery的朋友都知道他强大的链式操作,方便,简洁,易于理解,如下 $("has_children").click(function(){ $(this).addClass("highlight").children("a").show().end().siblings().removeClass("highlight").children("a").hide(); }); 1.jQuery的链式操作

jQery的链式操作和商城简易导航栏

今天要记录的是jq的一些简单操作.项目的需求是做一个导航栏,单机不同的商品名称链接,显示相应的内容.用js来写的话相对代码量要多一些,选择jqrey一行则可以搞定,下面呢是我的代码和效果图 这个是初始化点击后 首先是我们的布局部分,这里呢我直接把我的代码写进来,样式可能有点抽象 <style> .level1{ list-style: none; line-height: 30px; width: 100px; cursor: pointer; border-top: none; } .lev

tp5数据库——链式操作

链式操作 数据库提供的链式操作方法,可以有效的提高数据存取的代码清晰度和开发效率,并且支持所有的CURD操作. 使用也比较简单,假如我们现在要查询一个User表的满足状态为1的前10条记录,并希望按照用户的创建时间排序 ,代码如下: Db::table('think_user') ->where('status',1) ->order('create_time') ->limit(10) ->select(); 这里的where.order和limit方法就被称之为链式操作方法,除