最近看laravel4的代码,发现其中Config类(Repository)中的set和get方法并不是静态方法,但调用时却可以使用Config::get('app.url'), Config::set('app.url', 'http://xxx.xx')等
请问这个是如何实现的?
最近看laravel4的代码,发现其中Config类(Repository)中的set和get方法并不是静态方法,但调用时却可以使用Config::get('app.url'), Config::set('app.url', 'http://xxx.xx')等
请问这个是如何实现的?
使用了拦截器__callStatic
,当静态方式调用一个不存在的方法,会被这个方法拦截,第一个参数是静态调用方法名,第二个参数是一个包含调用方法参数的数组。他在拦截器方法里面做了处理,比如使用了call_user_func
去自动加载对应的方法。
看你贴的源码里面还有句延迟静态绑定,不过不重要,重要的就是这个拦截器。
写了一个简单的例子实现, 当然laravel比这个要复杂点,但是原理是一样的
class Config
{
private $self;
private $config = [];
private function getInstance()
{
if ($this->self === null) {
$this->self = new Config();
}
return $this->self;
}
protected function set($key, $value)
{
$this->config[$key] = $value;
return $this;
}
protected function get($key)
{
return $this->config[$key];
}
public static function __callStatic($method, $arguments)
{
$instance = static::getInstance();
if (method_exists($instance, $method)) {
return call_user_func_array([$instance, $method], $arguments);
}
throw new BadMethodCallException();
}
}
2 回答3.1k 阅读✓ 已解决
1 回答1.4k 阅读✓ 已解决
1 回答1k 阅读✓ 已解决
1 回答1.3k 阅读✓ 已解决
3 回答1.2k 阅读
2 回答1.2k 阅读
1 回答1.2k 阅读
请看依次下面代码。
Step 0
https://github.com/laravel/laravel/blob/master/app/config/app.php#L144
Step 1
https://github.com/laravel/framework/blob/master/src/Illuminate/Support/Facades/Config.php
Step 2
https://github.com/laravel/framework/blob/master/src/Illuminate/Support/Facades/Facade.php#L198
关键就是
__callStatic
方法的继承。在执行未定义的静态方法时,如果类方法中定义了这个__callStatic
,程序就会执行这个地方的代码。Config
类实际上是Illuminate\Support\Facades\Config
的别名,当调用
Config::set()
和Config::get()
静态方法时,就会执行Step 2
中的代码。$instance
就是Repository
的一个实例。