玩耍过jQuery的朋友们应该对链式操作不陌生,链式操作在实际应用上不仅美观,并且代码容易阅读,下面用PHP简单实现下链式操作。

1
$("#Test").css('color','red').show(200).removeClass('style'); //jquery中的链式操作

起步

先贴一波代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
class A {
private $name;
private $age; # 要改变的属性聚合在类中成为类属性
public function cname($name)
{
$this->name=$name;
return $this; # 链式操作的关键 方法中返回对象自身
}
public function cage($age)
{
$this->age=$age;
return $this;
}
public function __toString()
{
return 'name:'.$this->name.' age:'.$this->age;
}
}

实际调用

1
2
3
$instance = new A();
$instance->cage(111)->cname("Dawnki");
echo $instance; // name:Dawnki age:111

简单吧?如果是改变的属性为对象,即可进行更多的操作,这个代码风格使用起来也是十分顺手易读性强。

Laravel 使用的链式操作

Laravel在对数据库增删查询也是采用链式操作:

1
Model::where('xxx','xxx')->where('xxxxxx','xxxx')->get();

这里就会有个小问题,上面的链式操作明明都是return $this , 这里Model上来就搞了个where的静态方法,不会炸开锅吗?

实际上,阅读下Laravel的源码,里面采用了许多魔术方法,下面就看看源码的实现(好像有点偏题,哈哈)

在/vendor/laravel/illuminate/Database/Eloquent/Model.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
/**
* Handle dynamic method calls into the model.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
if (in_array($method, ['increment', 'decrement'])) {
return call_user_func_array([$this, $method], $parameters);
}
$query = $this->newQuery();
return call_user_func_array([$query, $method], $parameters);
}
/**
* Handle dynamic static method calls into the method.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public static function __callStatic($method, $parameters)
{
$instance = new static;
return call_user_func_array([$instance, $method], $parameters);
}

可见,当 Model:where(xxxx) 时,会先生成一个Model的实例(执行__callStatic),然后再用回调函数,让这个刚生成的实例去执行where,由于模型里面本来是没有涉及sql查询的方法,正在执行sql语句的是同目录下面的Builder.php,即SQL构造器,这个builder里面才负责处理SQL.因此Model的实例因为没有where方法而执行魔术方法__call来生成一个构造器(builder)去执行where方法。所以 真正执行where方法的是Builder.php

下面是/vendor/laravel/illuminate/Database/Eloquent/Builder中的where方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* Add a basic where clause to the query.
*
* @param string $column
* @param string $operator
* @param mixed $value
* @param string $boolean
* @return $this
*/
public function where($column, $operator = null, $value = null, $boolean =
'and')
{
if ($column instanceof Closure) {
$query = $this->model->newQueryWithoutScopes();
call_user_func($column, $query);
$this->query->addNestedWhereQuery($query->getQuery(), $boolean);
} else {
call_user_func_array([$this->query, 'where'], func_get_args());
}
return $this; # 链式操作关键
}

用链式操作改造CURL

附带一个利用链式操作的封装curl类

总结

所以不妨改良一下自己的代码吧!~