服务别名也相对重要,在很多地方使用。
通过服务绑定的别名,在解析服务的时候,跟不使用别名的效果一致。别名的作用也是为了同时支持全类型的服务绑定名称以及简短的服务绑定名称考虑的。
通俗的讲,假如我们想要创建 auth 服务,我们既可以这样写:
$this->app->make('auth')
又可以写成:
$this->app->make('\Illuminate\Auth\AuthManager::class')
还可以写成
$this->app->make('\Illuminate\Contracts\Auth\Factory::class')
后面两个服务的名字都是 auth 的别名,使用别名和使用 auth 的效果是相同的。
这里特别注意,谁是谁的别名
服务别名的获取
我们看下源码:
- 看看有没有对应的 $abstruct 的别名。如果没有就返回当前 $abstruct.
- 如果发现别名和 $abstruct 一样,抛出异常,别名不能和自己一样。
- 进一步递归,查看这个别名是否还有别名的别名。
public function getAlias($abstract)
{
if (! isset($this->aliases[$abstract])) {
return $abstract;
}
if ($this->aliases[$abstract] === $abstract) {
throw new LogicException("[{$abstract}] is aliased to itself.");
}
return $this->getAlias($this->aliases[$abstract]);
}
服务别名的实现
那么这些别名是如何加载到服务容器里面的呢?
两种方法:
- 通过调用 Container 中的 alias 方法,我们看下源代码 这里有两个数组:aliases 和 abstractAliases,他们保存一样的数据,但是键值对相反。简单说就是 aliases 的 key 值是
abstractAliases 的 value 值。下面有实例。 把 key 和 value 分别存储到对应的数组中。
public function alias($abstract, $alias)
{
$this->aliases[$alias] = $abstract;
$this->abstractAliases[$abstract][] = $alias;
}
- 外部配置引入。 其实原理也是一样,使用 alias () 方法,但是 laravel 在初始化的时候自己读取配置文件去存入对应数组中。 有两个地方,一个是 app.php 文件下的 alias 数组中,还有一个是在
laravel/framwork/src/Illuminate/Foundation/Application.php 下的
registerCoreContainerAliases 方法,这个方法在 Application
初始化的时候回加载。Application 是 Container 的子类,应用容器。后面再讨论。
看部分代码实例:
$aliases = [
'app' => [\Illuminate\Foundation\Application::class, \Illuminate\Contracts\Container\Container::class, \Illuminate\Contracts\Foundation\Application::class],
'auth' => [\Illuminate\Auth\AuthManager::class, \Illuminate\Contracts\Auth\Factory::class],
'auth.driver' => [\Illuminate\Contracts\Auth\Guard::class],
'blade.compiler' => [\Illuminate\View\Compilers\BladeCompiler::class],
'cache' => [\Illuminate\Cache\CacheManager::class, \Illuminate\Contracts\Cache\Factory::class],
...
]
运行的 registerCoreContainerAliases 方法。我们可以看到还是调用了 alias() 方法
public function registerCoreContainerAliases()
{
foreach ($aliases as $key => $aliases) {
foreach ($aliases as $alias) {
$this->alias($key, $alias);
}
}
}
加载后,服务容器的 aliases 和 abstractAliases 数组实例:
$aliases = [
'Illuminate\Foundation\Application' = "app"
'Illuminate\Contracts\Container\Container' = "app"
'Illuminate\Contracts\Foundation\Application' = "app"
'Illuminate\Auth\AuthManager' = "auth"
'Illuminate\Contracts\Auth\Factory' = "auth"
'Illuminate\Contracts\Auth\Guard' = "auth.driver"
'Illuminate\View\Compilers\BladeCompiler' = "blade.compiler"
'Illuminate\Cache\CacheManager' = "cache"
'Illuminate\Contracts\Cache\Factory' = "cache"
...
]
$abstractAliases = [
app = {array} [3]
0 = "Illuminate\Foundation\Application"
1 = "Illuminate\Contracts\Container\Container"
2 = "Illuminate\Contracts\Foundation\Application"
auth = {array} [2]
0 = "Illuminate\Auth\AuthManager"
1 = "Illuminate\Contracts\Auth\Factory"
auth.driver = {array} [1]
0 = "Illuminate\Contracts\Auth\Guard"
blade.compiler = {array} [1]
0 = "Illuminate\View\Compilers\BladeCompiler"
cache = {array} [2]
0 = "Illuminate\Cache\CacheManager"
1 = "Illuminate\Contracts\Cache\Factory"
...
]
我们在这里还是要特别强调:
数组 $abstractAliases 中,app 是 abstruct,后面跟着的三个数组元素才是‘app’的别名 (alias)
app = {array} [3]
0 = "Illuminate\Foundation\Application"
1 = "Illuminate\Contracts\Container\Container"
2 = "Illuminate\Contracts\Foundation\Application"
这里的这个结构需要指出的是,不管这个 app 别名有多少个,这些别名都指向一个 abstruct,这个 abstruct 又会指向数组
binding,binding 数组是建立 abstruct 和 concrete 关系的数组,而这个 $abstractAliases 和
$aliases 则是建立 abstruc 和 alias 之间关系的数组。
总结
别名机制就是用一个别名来命名具体对象,类或者闭包函数。他在 Facade 中有运用到,以及在容器绑定和解析都有用到。我们只要记住,他存储的两个数组名字:
1.abstractAliases
2.abstructs
我觉得他主要的作用可能就是让代码简介吧。
已测示例:
我们用别名 alias_money 重新命名了 Money::class
别名先找到‘money’再去找到 Money::class`
class ExampleTest extends TestCase
public function testClosure()
{
app()->bind('money', Money::class);
app()->alias('money','alias_money');
$boss= app()->make('alias_money');
$output = $boss->getAmount();
$this->assertEquals($output, 100);
}
}
class Money
{
public function getAmount(){
return 100;
}
}
————————————————
原文作者:HarveyNorman
转自链接:https://learnku.com/articles/41431
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。