源码小记 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 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

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