源码小记 Application 初始化 setBasePath
laravel version : 6.20.44
IDE : VsCode
代码追踪组件 : "barryvdh/laravel-ide-helper": "2.8"
这篇分析图片中的这一行代码
__construct
接收一个参数 $basePath
⌈应用的根路径⌉,相对于 ~/bootstrap/app.php
则是 dirname(__DIR__)
__DIR__: D:\MyCode\study\laravel\laravel6\bootstrap
dirname(__DIR__): D:\MyCode\study\laravel\laravel6
回到 __construct
方法,第一行调用 $this->setBasePath($basePath);
,为了方便查看,我把这行代码有关的代码单独分离了出来放进伪 class 文件里
<?php
class Path
{
protected $basePath; //根路径 D:\MyCode\study\laravel\laravel6
protected $appPath; // The custom application path defined by the developer.
protected $databasePath; // The custom database path defined by the developer.
protected $storagePath; // The custom storage path defined by the developer.
protected $environmentPath;// The custom environment path defined by the developer.
public function __construct($basePath = null)
{
if ($basePath) {
$this->setBasePath($basePath);
}
}
public function setBasePath($basePath)
{
$this->basePath = rtrim($basePath, '\/');
$this->bindPathsInContainer();
return $this;
}
protected function bindPathsInContainer()
{
$this->instance('path', $this->path());
$this->instance('path.base', $this->basePath());
$this->instance('path.lang', $this->langPath());
$this->instance('path.config', $this->configPath());
$this->instance('path.public', $this->publicPath());
$this->instance('path.storage', $this->storagePath());
$this->instance('path.database', $this->databasePath());
$this->instance('path.resources', $this->resourcePath());
$this->instance('path.bootstrap', $this->bootstrapPath());
}
public function path($path = '')
{
$appPath = $this->appPath ?: $this->basePath . DIRECTORY_SEPARATOR . 'app';
return $appPath . ($path ? DIRECTORY_SEPARATOR . $path : $path);
}
public function basePath($path = '')
{
return $this->basePath . ($path ? DIRECTORY_SEPARATOR . $path : $path);
}
public function langPath()
{
return $this->resourcePath() . DIRECTORY_SEPARATOR . 'lang';
}
public function configPath($path = '')
{
return $this->basePath . DIRECTORY_SEPARATOR . 'config' . ($path ? DIRECTORY_SEPARATOR . $path : $path);
}
public function publicPath()
{
return $this->basePath . DIRECTORY_SEPARATOR . 'public';
}
public function storagePath()
{
return $this->storagePath ?: $this->basePath . DIRECTORY_SEPARATOR . 'storage';
}
public function databasePath($path = '')
{
return ($this->databasePath ?: $this->basePath . DIRECTORY_SEPARATOR . 'database') . ($path ? DIRECTORY_SEPARATOR . $path : $path);
}
public function resourcePath($path = '')
{
return $this->basePath . DIRECTORY_SEPARATOR . 'resources' . ($path ? DIRECTORY_SEPARATOR . $path : $path);
}
public function bootstrapPath($path = '')
{
return $this->basePath . DIRECTORY_SEPARATOR . 'bootstrap' . ($path ? DIRECTORY_SEPARATOR . $path : $path);
}
public function useAppPath($path)
{
$this->appPath = $path;
$this->instance('path', $path);
return $this;
}
public function useStoragePath($path)
{
$this->storagePath = $path;
$this->instance('path.storage', $path);
return $this;
}
public function useDatabasePath($path)
{
$this->databasePath = $path;
$this->instance('path.database', $path);
return $this;
}
public function useEnvironmentPath($path)
{
$this->environmentPath = $path;
return $this;
}
}
分析
1. 定义了
$basePath
,$appPath
,$databasePath
,$storagePath
,$environmentPath
五个属性
思考:除了 $basePath
,为什么只定义这几个目录的属性,而 resources
,config
路径却没有定义属性?我们发现属性的注解写着 The custom
,说明这几个目录路径是允许自定义的。
2. 定义了
path($path = '')
,basePath($path = '')
,langPath()
,configPath($path = '')
,publicPath()
,storagePath()
,databasePath($path = '')
,resourcePath($path = '')
,bootstrapPath($path = '')
方法
一般情况下,在 $basePath
基础上拼接成路径,而允许自定义的属性是这样获取的:
有的方法接收 $path=''
参数,有的却没有,不太理解,感觉没什么区别,以至于助手函数 helpers
中对是否接收 $path=''
参数的方法调用都不同:
有 $path=''
参数的:
if (! function_exists('database_path')) {
function database_path($path = '')
{
return app()->databasePath($path);
}
}
没有 $path=''
参数的:
if (! function_exists('public_path')) {
function public_path($path = '')
{
return app()->make('path.public').($path ? DIRECTORY_SEPARATOR.ltrim($path, DIRECTORY_SEPARATOR) : $path);
}
}
if (! function_exists('storage_path')) {
function storage_path($path = '')
{
return app('path.storage').($path ? DIRECTORY_SEPARATOR.$path : $path);
}
}
有点意思,什么写法都有了
3. 将路径通过 instance($abstract, $instance)
放进 $instances
属性,打印 $instances
属性:
array:9 [
"path" => "D:\MyCode\study\laravel\laravel6\app" //custom
"path.base" => "D:\MyCode\study\laravel\laravel6"
"path.lang" => "D:\MyCode\study\laravel\laravel6\resources\lang"
"path.config" => "D:\MyCode\study\laravel\laravel6\config"
"path.public" => "D:\MyCode\study\laravel\laravel6\public"
"path.storage" => "D:\MyCode\study\laravel\laravel6\storage" //custom
"path.database" => "D:\MyCode\study\laravel\laravel6\database" //custom
"path.resources" => "D:\MyCode\study\laravel\laravel6\resources"
"path.bootstrap" => "D:\MyCode\study\laravel\laravel6\bootstrap"
];
4. 定义了
useAppPath($path)
,useStoragePath($path)
,useDatabasePath($path)
,useEnvironmentPath($path)
,
这四个方法也是对应四个可自定义的属性,在论坛中搜索 useAppPath
发现这篇文章
详解 packagit 用了什么黑魔法,并可完全替换 artisan 命令
本作品采用《CC 协议》,转载必须注明作者和本文链接