源码小记 Application 初始化 setBasePath

laravel version : 6.20.44
IDE : VsCode
代码追踪组件 : "barryvdh/laravel-ide-helper": "2.8"

这篇分析图片中的这一行代码

源码小记 容器初始化 setBasePath

__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 基础上拼接成路径,而允许自定义的属性是这样获取的:

源码小记 Application 初始化 setBasePath

有的方法接收 $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 协议》,转载必须注明作者和本文链接
welcome come back
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
95
粉丝
24
喜欢
156
收藏
348
排名:323
访问:2.9 万
私信
所有博文
社区赞助商