首頁 >後端開發 >php教程 >laravel - php非静态方法如何实现静态调用?

laravel - php非静态方法如何实现静态调用?

WBOY
WBOY原創
2016-06-06 20:47:181140瀏覽

最近看laravel4的代码,发现其中Config类(Repository)中的set和get方法并不是静态方法,但调用时却可以使用Config::get('app.url'), Config::set('app.url', 'http://xxx.xx')等

laravel - php非静态方法如何实现静态调用?

laravel - php非静态方法如何实现静态调用?

请问这个是如何实现的?

回复内容:

最近看laravel4的代码,发现其中Config类(Repository)中的set和get方法并不是静态方法,但调用时却可以使用Config::get('app.url'), Config::set('app.url', 'http://xxx.xx')等

laravel - php非静态方法如何实现静态调用?

laravel - php非静态方法如何实现静态调用?

请问这个是如何实现的?

请看依次下面代码。

Step 0

https://github.com/laravel/laravel/blob/master/app/config/app.php#L144

<code class="lang-php">'aliases' => array(
    'App'             => 'Illuminate\Support\Facades\App',
    'Artisan'         => 'Illuminate\Support\Facades\Artisan',
    'Auth'            => 'Illuminate\Support\Facades\Auth',
    'Blade'           => 'Illuminate\Support\Facades\Blade',
    'Cache'           => 'Illuminate\Support\Facades\Cache',
    'ClassLoader'     => 'Illuminate\Support\ClassLoader',
    'Config'          => 'Illuminate\Support\Facades\Config',
);
</code>

Step 1

https://github.com/laravel/framework/blob/master/src/Illuminate/Support/Facades/Config.php

<code class="lang-php"><?php namespace Illuminate\Support\Facades;

/**
 * @see \Illuminate\Config\Repository
 */
class Config extends Facade {

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor() { return 'config'; }

}
</code></code>

Step 2

https://github.com/laravel/framework/blob/master/src/Illuminate/Support/Facades/Facade.php#L198

<code class="lang-php">public static function __callStatic($method, $args)
{
    $instance = static::resolveFacadeInstance(static::getFacadeAccessor());

    switch (count($args))
    {
        case 0:
            return $instance->$method();

        case 1:
            return $instance->$method($args[0]);

        case 2:
            return $instance->$method($args[0], $args[1]);

        case 3:
            return $instance->$method($args[0], $args[1], $args[2]);

        case 4:
            return $instance->$method($args[0], $args[1], $args[2], $args[3]);

        default:
            return call_user_func_array(array($instance, $method), $args);
    }
}
</code>

关键就是 __callStatic 方法的继承。在执行未定义的静态方法时,如果类方法中定义了这个 __callStatic,程序就会执行这个地方的代码。

Config 类实际上是 Illuminate\Support\Facades\Config 的别名,

当调用 Config::set()Config::get() 静态方法时,就会执行 Step 2 中的代码。$instance 就是 Repository的一个实例。

使用了拦截器__callStatic,当静态方式调用一个不存在的方法,会被这个方法拦截,第一个参数是静态调用方法名,第二个参数是一个包含调用方法参数的数组。他在拦截器方法里面做了处理,比如使用了call_user_func去自动加载对应的方法。

看你贴的源码里面还有句延迟静态绑定,不过不重要,重要的就是这个拦截器。

PHP的namespace就是奇葩

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn