Laravel中Route类调用的是哪个类

背景:web.php中Route::get() 调用的是哪个类下的方法
这里的Route其实是个别名,在config/app.php中有设置,可以自己新建一个别名,然后在web.php里试下,知道了这个点后,就可以慢慢发现里面的奥秘。

'aliases' => [
    'Route' => Illuminate\Support\Facades\Route::class,
]

那么到底这里是如何通过别名来实现的呢?

其实没有什么思路,但是肯定的一点是用了配置文件的aliases,所以在整个项目中搜索“app.aliases”,所以在Illuminate\Foundation\Bootstrap\RegisterFacades.php中发现了它,这个类文件,其实也是在bootstrap的时候去运行的。

以下代码对不同文件中的方法进行了合并

public function bootstrap(Application $app)
{
    Facade::clearResolvedInstances();

    Facade::setFacadeApplication($app);

    AliasLoader::getInstance(array_merge(
        $app->make('config')->get('app.aliases', []),
        $app->make(PackageManifest::class)->aliases()
    ))->register();//注释1
}

public static function getInstance(array $aliases = [])
{
    if (is_null(static::$instance)) {//到这里去了
        return static::$instance = new static($aliases);//new了一个当前类
    }

    $aliases = array_merge(static::$instance->getAliases(), $aliases);

    static::$instance->setAliases($aliases);

    return static::$instance;
}

//运行注释1中的register方法
public function register()
{
    if (! $this->registered) {
        $this->prependToLoaderStack();

        $this->registered = true;
    }
}

protected function prependToLoaderStack()
{
    spl_autoload_register([$this, 'load'], true, true);
}

//$this->aliases是所有的对应别名,但是这里的$alias是怎么传入的呢???可以参考下面例子
/*
function load($className){
    echo $className;//打印ABC
}
spl_autoload_register('load', true, true);
$obj = new ABC();
*/
public function load($alias)
{
    if (static::$facadeNamespace && strpos($alias, static::$facadeNamespace) === 0) {
        $this->loadFacade($alias);

        return true;
    }

    if (isset($this->aliases[$alias])) {
        //设置Illuminate\Support\Facades\Route 别名为Route
        return class_alias($this->aliases[$alias], $alias);
    }
}

Illuminate\Support\Facades\Route又是怎么变成Illuminate\Routing\Router的呢?
因为Illuminate\Support\Facades\Route中没有get方法(web.php中route::get()使用),所以运行了父类Facade中的__callStatic方法

public static function __callStatic($method, $args)
{
    $instance = static::getFacadeRoot();

    if (! $instance) {
        throw new RuntimeException('A facade root has not been set.');
    }

    return $instance->$method(...$args);
}

public static function getFacadeRoot()
{
    return static::resolveFacadeInstance(static::getFacadeAccessor());//传的是router
}

//Illuminate\Support\Facades\Route.php中对getFacadeAccessor重写了
protected static function getFacadeAccessor()
{
    return 'router';
}

//app中的router给了它 !!!!!!!!!!!
protected static function resolveFacadeInstance($name)
{
    if (is_object($name)) {
        return $name;
    }

    if (isset(static::$resolvedInstance[$name])) {
        return static::$resolvedInstance[$name];
    }

    return static::$resolvedInstance[$name] = static::$app[$name];
}

但是 static::app); 把app赋值给了static::$app,那就只要看app中的router是哪里来的就可以了。
其实在laravel\bootstrap\app.php中一开始实列化后就有这个key了。

public function __construct($basePath = null)
{
    if ($basePath) {
        $this->setBasePath($basePath);
    }

    $this->registerBaseBindings();
    $this->registerBaseServiceProviders();
    $this->registerCoreContainerAliases();
}

  
protected function registerBaseServiceProviders()
{
    $this->register(new RoutingServiceProvider($this));
}

class RoutingServiceProvider extends ServiceProvider
{
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->registerRouter();
    }

    protected function registerRouter()
    {
        $this->app->singleton('router', function ($app) {
            return new Router($app['events'], $app);
        });
    }
}

接着调用Illuminate\Routing\Router.php的convertToControllerAction方法,来获取实际的controller是什么。app\Providers\RouteServiceProvider.php中有设置了namespace,就是controller的位置在App\Http\Controllers
到这里就把所有的问题解释清楚了。

===========
2021-04-15更新

所以Route::get();可以直接这么使用

make('config')->get('app.aliases', []),
            $app->make(PackageManifest::class)->aliases()
        ))->register();

        
$this->prependToLoaderStack();


spl_autoload_register([$this, 'load'], true, true);


if (isset($this->aliases[$alias])) {
    return class_alias($this->aliases[$alias], $alias);
}
*/
class A{

}
class_alias('A', 'B');

$obj = new B;
echo "
";
var_dump($obj);

你可能感兴趣的:(Laravel中Route类调用的是哪个类)