深入研究 Laravel 原始碼第二天

chonghua_123發表於2018-11-17

前言

上一篇文章,研究了larvael框架入口檔案 index.php,這一篇深入研究 獲取框架例項底層程式碼
至於 composer自動載入原始碼分析請到這觀看


bootstrap/app.php檔案分析

 $app = new Illuminate\Foundation\Application(
    realpath(__DIR__.'/../')
);

$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Http\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Console\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);

return $app;
  1. 第一步 獲取應用例項
  2. 第二步 繫結框架核心 http核心,控制檯核心,異常處理單例


Illuminate\Foundation\Application檔案分析

1. 引入

use Closure;   //PHP 匿名函式類
use RuntimeException; //php 執行異常類
use Illuminate\Support\Arr; //框架支援的arr類
use Illuminate\Support\Str;//框架支援的str類
use Illuminate\Http\Request;//框架http 請求類
use Illuminate\Support\Collection;//框架支援的集合類
use Illuminate\Container\Container;//框架容器核心類
use Illuminate\Filesystem\Filesystem;//框架檔案系統的檔案類
use Illuminate\Log\LogServiceProvider;//框架日誌元件日誌服務提供者
use Illuminate\Support\ServiceProvider;//框架支援的服務提供者
use Illuminate\Events\EventServiceProvider;//框架事件系統的事件服務提供者
use Illuminate\Routing\RoutingServiceProvider;//框架路由元件的路由服務提供者
use Symfony\Component\HttpKernel\HttpKernelInterface;//Symfony框架http核心介面
use Symfony\Component\HttpKernel\Exception\HttpException;//Symfony框架http核心異常下http異常類
use Illuminate\Contracts\Http\Kernel as HttpKernelContract;//框架http核心契約
use Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables;//框架基礎載入環境變數類
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;//Symfony框架http請求類
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;//Symfony框架http核心異常類
use Illuminate\Contracts\Foundation\Application as ApplicationContract;//框架契約基礎類

2. 定義類定義屬性

class Application extends Container implements ApplicationContract, HttpKernelInterface
{//定義Application物件繼承Container,實現ApplicationContract, HttpKernelInterface
    const VERSION = '5.7.12'; //版本號
    protected $basePath;//基本路徑
    protected $hasBeenBootstrapped = false;//應用程式是否已被自舉。
    protected $booted = false;//引用程式是否已啟動
    protected $bootingCallbacks = [];//引導回撥的陣列
    protected $bootedCallbacks = [];//啟動回撥的陣列
    protected $terminatingCallbacks = [];//終止回撥的陣列
    protected $serviceProviders = [];//註冊的服務提供者
    protected $loadedProviders = [];//載入的服務提供者的名稱
    protected $deferredServices = [];//延遲的服務提供者的名稱
    protected $databasePath;//資料庫路徑
    protected $storagePath;//儲存路徑
    protected $environmentPath;//環境變數路徑
    protected $environmentFile = '.env';//環境變數檔案
    protected $namespace;//應用程式名稱空間

3. 建構函式,初始化處理

1、setBasePath // 設定應用基礎路徑
2、registerBaseBindings // 繫結容器中的所有應用程式路徑
3、registerBaseServiceProviders // 註冊基本繫結
4、registerCoreContainerAliases //註冊容器核心類別名

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

4. 設定基礎路徑

1、bindPathsInContainer

    public function setBasePath($basePath)
    {
        $this->basePath = rtrim($basePath, '\/');
        $this->bindPathsInContainer();
        return $this;
    }

5. 繫結容器中的所有應用程式路徑

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());
}

6. 將基本繫結註冊到容器中

1、static::setInstance
2、instance

       protected function registerBaseBindings()
     {
        static::setInstance($this);//設定全域性容器可用例項
        $this->instance('app', $this);//繫結當前例項到app
        $this->instance(Container::class, $this);//繫結當前例項到Container
        $this->instance(PackageManifest::class, new PackageManifest(
            new Filesystem, $this->basePath(), $this->getCachedPackagesPath()
        ));//檔案例項繫結到PackageManifest
    }

7. 註冊所有的基礎服務提供者

1、register

protected function registerBaseServiceProviders()
    {
        $this->register(new EventServiceProvider($this));//1. 事件服務提供者        
        $this->register(new LogServiceProvider($this));// 2. 日誌服務提供者
        $this->register(new RoutingServiceProvider($this));  //3. 路由服務提供者
    }

8. 註冊方法剖析

1、getProvider
2、resolveProvider
3、bind
4、singleton
5、markAsRegistered
6、bootProvider
7、參考連結

   public function register($provider, $force = false)
    {
        //判斷該服務提供者是否已註冊,已經註冊直接返回例項
        if (($registered = $this->getProvider($provider)) && ! $force) {
            return $registered;
        }
        //如果傳入一個字串(類名)
        if (is_string($provider)) {
            //直接去例項化(直白點就是new 這個類)
            $provider = $this->resolveProvider($provider);
        }
        //如果該服務提供者存在register方法,直接執行
        if (method_exists($provider, 'register')) {
            $provider->register();
        }
       //如果服務提供者包含bindings屬性,則進行
        if (property_exists($provider, 'bindings')) {
            foreach ($provider->bindings as $key => $value) {
                $this->bind($key, $value);
            }
        }
        //如果服務提供者包含singletons屬性,則進行
        if (property_exists($provider, 'singletons')) {
            foreach ($provider->singletons as $key => $value) {
                $this->singleton($key, $value);
            }
        }
        //標記該程式為已註冊,加入已註冊服務提供者陣列和已載入服務提供者陣列
        $this->markAsRegistered($provider);
        //如果程式已啟動,呼叫服務提供者boot方法
        if ($this->booted) {
            $this->bootProvider($provider);
        }
        //返回例項
        return $provider;
    }

9. 獲取版本號

        public function version()

10. 註冊回撥以在載入環境之後執行

    public function afterLoadingEnvironment(Closure $callback)
    {
        return $this->afterBootstrapping(
            LoadEnvironmentVariables::class, $callback
        );
    }

11. 註冊回撥以在載入程式之後執行

   public function afterBootstrapping($bootstrapper, Closure $callback)
    {
        $this['events']->listen('bootstrapped: '.$bootstrapper, $callback);//監聽引導後事件
    }

12. 註冊回撥在載入程式之前執行

  public function beforeBootstrapping($bootstrapper, Closure $callback)
    {
        $this['events']->listen('bootstrapping: '.$bootstrapper, $callback);//監聽引導前事件
    }

13. 是否程式自舉

  public function hasBeenBootstrapped()
    {
        return $this->hasBeenBootstrapped;
    }

14. 獲取app目錄路徑

 public function path($path = '')
    {
        return $this->basePath.DIRECTORY_SEPARATOR.'app'.($path ? DIRECTORY_SEPARATOR.$path : $path);
    }

15. 獲取laravel根路徑

public function basePath($path = '')
    {
        return $this->basePath.($path ? DIRECTORY_SEPARATOR.$path : $path);
    }

16. 獲取bootstrap路徑

public function bootstrapPath($path = '')
    {
        return $this->basePath.DIRECTORY_SEPARATOR.'bootstrap'.($path ? DIRECTORY_SEPARATOR.$path : $path);
    }

17. 獲取config路徑

public function configPath($path = '')
    {
        return $this->basePath.DIRECTORY_SEPARATOR.'config'.($path ? DIRECTORY_SEPARATOR.$path : $path);
    }

18. 獲取database路徑

 public function databasePath($path = '')
    {
        return ($this->databasePath ?: $this->basePath.DIRECTORY_SEPARATOR.'database').($path ? DIRECTORY_SEPARATOR.$path : $path);
    }

19. 設定databsee路徑

public function useDatabasePath($path)
    {
        $this->databasePath = $path;

        $this->instance('path.database', $path);//新增到容器裡

        return $this;
    }

20. 獲取資源resource路徑

public function resourcePath($path = '')
    {
        return $this->basePath.DIRECTORY_SEPARATOR.'resources'.($path ? DIRECTORY_SEPARATOR.$path : $path);
    }

21. 獲取public路徑

public function publicPath()
    {
        return $this->basePath.DIRECTORY_SEPARATOR.'public';
    }

22. 獲取語言包路徑

public function langPath()
    {
        return $this->resourcePath().DIRECTORY_SEPARATOR.'lang';
    }

23. 獲取strorge的路徑

public function storagePath()
    {
        return $this->storagePath ?: $this->basePath.DIRECTORY_SEPARATOR.'storage';
    }

24. 設定strorge的路徑

 public function useStoragePath($path)
    {
        $this->storagePath = $path;
        $this->instance('path.storage', $path);
        return $this;
    }

26. 獲取env路徑

public function environmentPath()
    {
        return $this->environmentPath ?: $this->basePath;
    }

27. 設定env路徑

    public function useEnvironmentPath($path)
    {
        $this->environmentPath = $path;

        return $this;
    }

28. 設定env檔案

public function loadEnvironmentFrom($file)
    {
        $this->environmentFile = $file;

        return $this;
    }

29. 獲取env檔案

 public function environmentFile()
    {
        return $this->environmentFile ?: '.env';
    }

29. 獲取env檔案路徑

public function environmentFilePath()
    {
        return $this->environmentPath().DIRECTORY_SEPARATOR.$this->environmentFile();
    }

30. 獲取應用env配置

public function environment()
    {
        //判斷是否有引數
        if (func_num_args() > 0) {
            $patterns = is_array(func_get_arg(0)) ? func_get_arg(0) : func_get_args();
            return Str::is($patterns, $this['env']);//字串搜尋
        }
        return $this['env'];
    }

31. 環境是否本地開發

 public function isLocal()
    {
        return $this['env'] === 'local';
    }

32. 檢測應用當前環境 detect方法詳解

 public function detectEnvironment(Closure $callback)
    {
        $args = $_SERVER['argv'] ?? null;//獲取cli模式下的引數

        return $this['env'] = (new EnvironmentDetector)->detect($callback, $args);//
    }

33. 確定應用是否在控制檯執行

 public function runningInConsole()
    {
        if (isset($_ENV['APP_RUNNING_IN_CONSOLE'])) {
            return $_ENV['APP_RUNNING_IN_CONSOLE'] === 'true';
        }

        return php_sapi_name() === 'cli' || php_sapi_name() === 'phpdbg';//cli模式或者phpdbg除錯模式
    }

34. 確定應用是否執行在unit單元測試

public function runningUnitTests()
    {
        return $this['env'] === 'testing';
    }

35. 註冊所有配置的提供程式

public function registerConfiguredProviders()
    {
        $providers = Collection::make($this->config['app.providers'])//建立一個集合例項從app.php獲取到的服務提供者陣列
                        ->partition(function ($provider) {
                            return Str::startsWith($provider, 'Illuminate\\');//判斷是否已$needles字串開頭
                        });//*使用給定的回撥或鍵將集合劃分為兩個陣列。一部分框架核心一部分自定義

       //將所有包的所有服務提供者類名填充到1的位置
        $providers->splice(1, 0, [$this->make(PackageManifest::class)->providers()]);獲取所。

        //存入服務提供者快取檔案 
        (new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath()))
                    ->load($providers->collapse()->toArray());
    }

36. 如果已註冊服務提供程式例項存在,則獲取該例項


    public function getProvider($provider)
    {
        return array_values($this->getProviders($provider))[0] ?? null;
    }

37. 獲取所有註冊的服務提供者

 public function getProviders($provider)
    {
        $name = is_string($provider) ? $provider : get_class($provider);//獲取類名稱

        return Arr::where($this->serviceProviders, function ($value) use ($name) {
            return $value instanceof $name;//判斷是否是例項
        });
    }

38. 類名解析服務提供者例項

 public function resolveProvider($provider)
    {
        return new $provider($this);
    }

39. 標記程式為已註冊

protected function markAsRegistered($provider)
    {
        $this->serviceProviders[] = $provider;

        $this->loadedProviders[get_class($provider)] = true;
    }

40. 載入所有延遲服務提供者

 public function loadDeferredProviders()
    {

        foreach ($this->deferredServices as $service => $provider) {
            $this->loadDeferredProvider($service);//迴圈載入延遲服務提供者
        }
        $this->deferredServices = [];//將延遲服務提供者置為空
    }

41. 載入延遲服務提供者

public function loadDeferredProvider($service)
    {
       //判斷是否屬於延遲服務提供者
        if (! isset($this->deferredServices[$service])) {
            return;
        }
        //判斷是否已載入
        if (! isset($this->loadedProviders[$provider])) {
            //註冊延遲服務提供者
            $this->registerDeferredProvider($provider, $service);
        }
    }

42. 註冊延遲服務提供者

public function registerDeferredProvider($provider, $service = null)
    {
        if ($service) {
            unset($this->deferredServices[$service]);//將該服務清空出延時服務提供者陣列
        }
        $this->register($instance = new $provider($this));//註冊服務
        if (! $this->booted) {
            $this->booting(function () use ($instance) {
                $this->bootProvider($instance);//啟動服務呼叫boot
            });
        }
    }

43. 從容器中解析例項

1、getAlias
2、parent::make

 public function make($abstract, array $parameters = [])
    {
        $abstract = $this->getAlias($abstract);//獲取別名
         //如果是延遲服務提供者並且沒有例項化就載入延遲程式
        if (isset($this->deferredServices[$abstract]) && ! isset($this->instances[$abstract])) {
            $this->loadDeferredProvider($abstract);
        }

        return parent::make($abstract, $parameters);//使用父類方法解析例項並返回
    }

44. 確定給定的抽象型別是否已經被繫結

1、parent::bound

 public function bound($abstract)
    {
        return isset($this->deferredServices[$abstract]) || parent::bound($abstract);
    }

45. 應用是否已啟動

public function isBooted()
    {
        return $this->booted;
    }

46. 啟動應用

1、fireAppCallbacks

    public function boot()
    {
        if ($this->booted) {
            return;
        }
        //呼叫引導回撥
        $this->fireAppCallbacks($this->bootingCallbacks);
        array_walk($this->serviceProviders, function ($p) {
            $this->bootProvider($p);//啟動服務提供者
        });
        $this->booted = true;//設定程式已啟動
        //呼叫啟動後
        $this->fireAppCallbacks($this->bootedCallbacks);
    }

47. 啟動服務提供者

protected function bootProvider(ServiceProvider $provider)
    {
        if (method_exists($provider, 'boot')) {
            return $this->call([$provider, 'boot']);
        }
    }

48. 設定應用引導回撥陣列

public function booting($callback)
    {
        $this->bootingCallbacks[] = $callback;
    }

49. 設定應用啟動回撥陣列

public function booted($callback)
    {
        $this->bootedCallbacks[] = $callback;

        if ($this->isBooted()) {
            $this->fireAppCallbacks([$callback]);//如果已啟動,呼叫回撥
        }
    }

50. 呼叫程式回撥

protected function fireAppCallbacks(array $callbacks)
    {
        foreach ($callbacks as $callback) {
            call_user_func($callback, $this);
        }
    }

51. handle

public function handle(SymfonyRequest $request, $type = self::MASTER_REQUEST, $catch = true)
    {
        return $this[HttpKernelContract::class]->handle(Request::createFromBase($request));
    }

52. shouldSkipMiddleware

1、bound
2、make

public function shouldSkipMiddleware()
    {
        return $this->bound('middleware.disable') &&
               $this->make('middleware.disable') === true;
    }```
### 53. <a name="getCachedServicesPath">獲取快取服務路徑</a>
1、<a href="#bootstrapPath">bootstrapPath</a>
```php
public function getCachedServicesPath()
    {
        return $this->bootstrapPath().'/cache/services.php';
    }

54. 獲取packages.php的路徑

1、bootstrapPath

public function getCachedPackagesPath()
    {
        return $this->bootstrapPath().'/cache/packages.php';
    }

55. 確定是否快取了應用程式配置

1、getCachedConfigPath

public function configurationIsCached()
    {
        return file_exists($this->getCachedConfigPath());
    }

56. 獲取config檔案路徑

1、bootstrapPath

 public function getCachedConfigPath()
    {
        return $this->bootstrapPath().'/cache/config.php';
    }

57. 確定是否快取了路由配置

1、getCachedRoutesPath

public function routesAreCached()
    {
        return $this['files']->exists($this->getCachedRoutesPath());
    }

58. 獲取路由快取路徑

1、bootstrapPath

 public function getCachedRoutesPath()
    {
        return $this->bootstrapPath().'/cache/routes.php';
    }

59. 確定應用程式當前是否停機進行維護

1、storagePath

public function isDownForMaintenance()
    {
        return file_exists($this->storagePath().'/framework/down');
    }

60. 丟擲http異常

 public function abort($code, $message = '', array $headers = [])
    {
        if ($code == 404) {
            throw new NotFoundHttpException($message);
        }

        throw new HttpException($code, $message, null, $headers);
    }

61. 設定程式終止的回撥

public function terminating(Closure $callback)
    {
        $this->terminatingCallbacks[] = $callback;

        return $this;
    }

62. 執行終止程式回撥

 public function terminate()
    {
        foreach ($this->terminatingCallbacks as $terminating) {
            $this->call($terminating);
        }
    }

63. 獲取所有已載入的服務提供者

 public function getLoadedProviders()
    {
        return $this->loadedProviders;
    }

64. 獲取所有延遲載入服務提供者

 public function getDeferredServices()
    {
        return $this->deferredServices;
    }

65. 設定延遲服務提供者

public function setDeferredServices(array $services)
    {
        $this->deferredServices = $services;
    }

66. 新增延遲服務提供者

public function addDeferredServices(array $services)
    {
        $this->deferredServices = array_merge($this->deferredServices, $services);
    }

67. 驗證是否是延遲服務提供者

 public function isDeferredService($service)
    {
        return isset($this->deferredServices[$service]);
    }

68. 設定服務門面名稱空間

1、AliasLoader::setFacadeNamespace

public function provideFacades($namespace)
    {
        AliasLoader::setFacadeNamespace($namespace);
    }

69. 獲取當前區域設定

public function getLocale()
    {
        return $this['config']->get('app.locale');
    }

70. 設定當前區域

public function setLocale($locale)
    {
        $this['config']->set('app.locale', $locale);

        $this['translator']->setLocale($locale);

        $this['events']->dispatch(new Events\LocaleUpdated($locale));
    }

71. 判斷當前區域

 public function isLocale($locale)
    {
        return $this->getLocale() == $locale;
    }

72. 在容器中註冊核心類別名

1、alias

    public function registerCoreContainerAliases()
    {
        foreach ([
            'app'                  => [\Illuminate\Foundation\Application::class, \Illuminate\Contracts\Container\Container::class, \Illuminate\Contracts\Foundation\Application::class,  \Psr\Container\ContainerInterface::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],
            'cache.store'          => [\Illuminate\Cache\Repository::class, \Illuminate\Contracts\Cache\Repository::class],
            'config'               => [\Illuminate\Config\Repository::class, \Illuminate\Contracts\Config\Repository::class],
            'cookie'               => [\Illuminate\Cookie\CookieJar::class, \Illuminate\Contracts\Cookie\Factory::class, \Illuminate\Contracts\Cookie\QueueingFactory::class],
            'encrypter'            => [\Illuminate\Encryption\Encrypter::class, \Illuminate\Contracts\Encryption\Encrypter::class],
            'db'                   => [\Illuminate\Database\DatabaseManager::class],
            'db.connection'        => [\Illuminate\Database\Connection::class, \Illuminate\Database\ConnectionInterface::class],
            'events'               => [\Illuminate\Events\Dispatcher::class, \Illuminate\Contracts\Events\Dispatcher::class],
            'files'                => [\Illuminate\Filesystem\Filesystem::class],
            'filesystem'           => [\Illuminate\Filesystem\FilesystemManager::class, \Illuminate\Contracts\Filesystem\Factory::class],
            'filesystem.disk'      => [\Illuminate\Contracts\Filesystem\Filesystem::class],
            'filesystem.cloud'     => [\Illuminate\Contracts\Filesystem\Cloud::class],
            'hash'                 => [\Illuminate\Hashing\HashManager::class],
            'hash.driver'          => [\Illuminate\Contracts\Hashing\Hasher::class],
            'translator'           => [\Illuminate\Translation\Translator::class, \Illuminate\Contracts\Translation\Translator::class],
            'log'                  => [\Illuminate\Log\LogManager::class, \Psr\Log\LoggerInterface::class],
            'mailer'               => [\Illuminate\Mail\Mailer::class, \Illuminate\Contracts\Mail\Mailer::class, \Illuminate\Contracts\Mail\MailQueue::class],
            'auth.password'        => [\Illuminate\Auth\Passwords\PasswordBrokerManager::class, \Illuminate\Contracts\Auth\PasswordBrokerFactory::class],
            'auth.password.broker' => [\Illuminate\Auth\Passwords\PasswordBroker::class, \Illuminate\Contracts\Auth\PasswordBroker::class],
            'queue'                => [\Illuminate\Queue\QueueManager::class, \Illuminate\Contracts\Queue\Factory::class, \Illuminate\Contracts\Queue\Monitor::class],
            'queue.connection'     => [\Illuminate\Contracts\Queue\Queue::class],
            'queue.failer'         => [\Illuminate\Queue\Failed\FailedJobProviderInterface::class],
            'redirect'             => [\Illuminate\Routing\Redirector::class],
            'redis'                => [\Illuminate\Redis\RedisManager::class, \Illuminate\Contracts\Redis\Factory::class],
            'request'              => [\Illuminate\Http\Request::class, \Symfony\Component\HttpFoundation\Request::class],
            'router'               => [\Illuminate\Routing\Router::class, \Illuminate\Contracts\Routing\Registrar::class, \Illuminate\Contracts\Routing\BindingRegistrar::class],
            'session'              => [\Illuminate\Session\SessionManager::class],
            'session.store'        => [\Illuminate\Session\Store::class, \Illuminate\Contracts\Session\Session::class],
            'url'                  => [\Illuminate\Routing\UrlGenerator::class, \Illuminate\Contracts\Routing\UrlGenerator::class],
            'validator'            => [\Illuminate\Validation\Factory::class, \Illuminate\Contracts\Validation\Factory::class],
            'view'                 => [\Illuminate\View\Factory::class, \Illuminate\Contracts\View\Factory::class],
        ] as $key => $aliases) {
            foreach ($aliases as $alias) {
                $this->alias($key, $alias);
            }
        }
    }

73. 清除所有繫結和解決例項的容器

1、parent::flush

    public function flush()
    {
        parent::flush();
        $this->buildStack = [];
        $this->loadedProviders = [];
        $this->bootedCallbacks = [];
        $this->bootingCallbacks = [];
        $this->deferredServices = [];
        $this->reboundCallbacks = [];
        $this->serviceProviders = [];
        $this->resolvingCallbacks = [];
        $this->afterResolvingCallbacks = [];
        $this->globalResolvingCallbacks = [];
    }

74. 獲取名稱空間

    public function getNamespace()
    {
        if (! is_null($this->namespace)) {
            return $this->namespace;
        }
        $composer = json_decode(file_get_contents(base_path('composer.json')), true);
        foreach ((array) data_get($composer, 'autoload.psr-4') as $namespace => $path) {
            foreach ((array) $path as $pathChoice) {
                if (realpath(app_path()) == realpath(base_path().'/'.$pathChoice)) {
                    return $this->namespace = $namespace;
                }
            }
        }
        throw new RuntimeException('Unable to detect application namespace.');
    }

75. 執行給定的引導類陣列

public function bootstrapWith(array $bootstrappers)
    {
        $this->hasBeenBootstrapped = true;

        foreach ($bootstrappers as $bootstrapper) {
            $this['events']->dispatch('bootstrapping: '.$bootstrapper, [$this]);

            $this->make($bootstrapper)->bootstrap($this);

            $this['events']->dispatch('bootstrapped: '.$bootstrapper, [$this]);
        }
    }

相關文章