你知道Laravel的$this->app以及app()是怎么来的吗?

 6108

下面给大家介绍Laravel的$this->app以及app()是怎么来的,希望对需要的朋友有所帮助!


断点调试寻找对应文件,忽略次要步骤,仅描述核心动作,‘/’表示index.php所在目录

地址:index.php

  1. $app = require_once __DIR__.'/../bootstrap/app.php';


$app初始化

路径/…/bootstrap/app.php

  1. $app = new Illuminate\Foundation\Application(
  2.     realpath(__DIR__.'/../')
  3. );
  4. //$app初始化工作

$app初始化的类及构造函数

  1. class Application extends Container implements ApplicationContract,HttpKernelInterface
  2. {
  3.     //继承Container类,Container类实现应用契约接口与请求接口
  4.     public function __construct($basePath = null){
  5.         if ($basePath) {//$basePath = '/../'
  6.             $this->setBasePath($basePath);//路径绑定
  7.         }
  8.        $this->registerBaseBindings();//基础绑定
  9.        $this->registerBaseServiceProviders();//注册基础服务提供者
  10.        $this->registerCoreContainerAliases();//注册别名
  11.     }
  12. }

路径绑定

Application的setBasePath(’/…/’)方法调用Container的instance(a b s t r a c t , abstract,abstract,instance)方法赋值Contaienr类instances

  1. instances: array:9 [
  2.     "path" => "\var\www\app"
  3.     "path.base" => "\var\www"
  4.     "path.lang" => "\var\www\resources\lang"
  5.     "path.config" => "\var\www\config"
  6.     "path.public" => "\var\www\public"
  7.     "path.storage" => "\var\www\storage"
  8.     "path.database" => "\var\www\database"
  9.     "path.resources" => "\var\www\resources"
  10.     "path.bootstrap" => "\var\www\bootstrap"
  11. ]

基础绑定

向Container的instances中添加绑定

  1. "app" => Application {#2}
  2. "Illuminate\Container\Container" => Application {#2}
  3. "Illuminate\Foundation\PackageManifest" => PackageManifest {#4 
  4.     +files: Filesystem {#5}
  5.     +basePath: "\var\www"
  6.     +vendorPath: "\var\www\vendor"
  7.     +manifestPath: "\var\www\bootstrap\cache\packages.php"
  8.     +manifest: null
  9. }


app与Container指向当前实例

PackageMainfest 为包管理实例,构造方法中files注册文件系统实例

注册基础服务提供者

  1. //class Application
  2. protected function registerBaseServiceProviders()
  3. {
  4.     $this->register(new EventServiceProvider($this));
  5.     $this->register(new LogServiceProvider($this));
  6.     $this->register(new RoutingServiceProvider($this));
  7. }

Event、Log、Routing基础服务继承ServiceProvider,初始化的时候将app属性赋值Application实例

  1. //class ServiceProvider    
  2. public function __construct($app)
  3. {
  4.     $this->app = $app;
  5. }

执行Application类register方法

  1. //Application
  2. public function register($provider, $options = [], $force = false)
  3. {
  4.     if (is_string($provider)) {
  5.         $provider = $this->resolveProvider($provider);
  6.     }
  7.     if (method_exists($provider, 'register')) {
  8.         $provider->register();//赋值bindings
  9.     }
  10.     //将服务提供者添加到serviceProviders属性队列
  11.     //将服务提供者类名添加到loaderProviders属性
  12.     $this->markAsRegistered($provider);
  13.     return $provider;
  14. }

为provider注册提供了两种方法;

一种是字符串类名直接实例,

一种是执行$$provider->register()方法注册,

当前执行第二种方法,

回看当前EventServiceProvider实例的register方法

  1. public function register()
  2. {
  3.     $this->app->singleton('events', function ($app) {
  4.         return (new Dispatcher($app))->setQueueResolver(function () use ($app) {
  5.             return $app->make(QueueFactoryContract::class);
  6.         });
  7.     });
  8. }

调用Application实例的singleton方法

  1. //class Continer
  2. public function singleton($abstract, $concrete = null)
  3. {
  4.     $this->bind($abstract, $concrete, true);
  5. }

调用bind方法,赋值bindings

  1. //class Container
  2. public function bind($abstract, $concrete = null, $shared = false)
  3. {
  4.     if (is_null($concrete)) {
  5.         $concrete = $abstract;
  6.     }
  7.     if (! $concrete instanceof Closure) {
  8.         $concrete = $this->getClosure($abstract, $concrete);
  9.     }
  10.     $this->bindings[$abstract] = compact('concrete', 'shared');
  11. }

回到Application类register方法中并执行markAsRegistered($provider)

  1. //class Application
  2. protected function markAsRegistered($provider)
  3. {
  4.     $this->serviceProviders[] = $provider;
  5.     $this->loadedProviders[get_class($provider)] = true;
  6. }

LogServerProvider、RoutingServiceProvider与之类似

别名绑定

  1. //class Application
  2. public function registerCoreContainerAliases()
  3. {
  4.     foreach ([
  5.         'app'                  => [self::class, \Illuminate\Contracts\Container\Container::class, \Illuminate\Contracts\Foundation\Application::class,  \Psr\Container\ContainerInterface::class],
  6.         'auth'                 => [\Illuminate\Auth\AuthManager::class, \Illuminate\Contracts\Auth\Factory::class],
  7.         'auth.driver'          => [\Illuminate\Contracts\Auth\Guard::class],
  8.         'blade.compiler'       => [\Illuminate\View\Compilers\BladeCompiler::class],
  9.         'cache'                => [\Illuminate\Cache\CacheManager::class, \Illuminate\Contracts\Cache\Factory::class],
  10.         'cache.store'          => [\Illuminate\Cache\Repository::class, \Illuminate\Contracts\Cache\Repository::class],
  11.         'config'               => [\Illuminate\Config\Repository::class, \Illuminate\Contracts\Config\Repository::class],
  12.         'cookie'               => [\Illuminate\Cookie\CookieJar::class, \Illuminate\Contracts\Cookie\Factory::class, \Illuminate\Contracts\Cookie\QueueingFactory::class],
  13.         'encrypter'            => [\Illuminate\Encryption\Encrypter::class, \Illuminate\Contracts\Encryption\Encrypter::class],
  14.         'db'                   => [\Illuminate\Database\DatabaseManager::class],
  15.         'db.connection'        => [\Illuminate\Database\Connection::class, \Illuminate\Database\ConnectionInterface::class],
  16.         'events'               => [\Illuminate\Events\Dispatcher::class, \Illuminate\Contracts\Events\Dispatcher::class],
  17.         'files'                => [\Illuminate\Filesystem\Filesystem::class],
  18.         'filesystem'           => [\Illuminate\Filesystem\FilesystemManager::class, \Illuminate\Contracts\Filesystem\Factory::class],
  19.         'filesystem.disk'      => [\Illuminate\Contracts\Filesystem\Filesystem::class],
  20.         'filesystem.cloud'     => [\Illuminate\Contracts\Filesystem\Cloud::class],
  21.         'hash'                 => [\Illuminate\Contracts\Hashing\Hasher::class],
  22.         'translator'           => [\Illuminate\Translation\Translator::class, \Illuminate\Contracts\Translation\Translator::class],
  23.         'log'                  => [\Illuminate\Log\Writer::class, \Illuminate\Contracts\Logging\Log::class, \Psr\Log\LoggerInterface::class],
  24.         'mailer'               => [\Illuminate\Mail\Mailer::class, \Illuminate\Contracts\Mail\Mailer::class, \Illuminate\Contracts\Mail\MailQueue::class],
  25.         'auth.password'        => [\Illuminate\Auth\Passwords\PasswordBrokerManager::class, \Illuminate\Contracts\Auth\PasswordBrokerFactory::class],
  26.         'auth.password.broker' => [\Illuminate\Auth\Passwords\PasswordBroker::class, \Illuminate\Contracts\Auth\PasswordBroker::class],
  27.         'queue'                => [\Illuminate\Queue\QueueManager::class, \Illuminate\Contracts\Queue\Factory::class, \Illuminate\Contracts\Queue\Monitor::class],
  28.         'queue.connection'     => [\Illuminate\Contracts\Queue\Queue::class],
  29.         'queue.failer'         => [\Illuminate\Queue\Failed\FailedJobProviderInterface::class],
  30.         'redirect'             => [\Illuminate\Routing\Redirector::class],
  31.         'redis'                => [\Illuminate\Redis\RedisManager::class, \Illuminate\Contracts\Redis\Factory::class],
  32.         'request'              => [\Illuminate\Http\Request::class, \Symfony\Component\HttpFoundation\Request::class],
  33.         'router'               => [\Illuminate\Routing\Router::class, \Illuminate\Contracts\Routing\Registrar::class, \Illuminate\Contracts\Routing\BindingRegistrar::class],
  34.         'session'              => [\Illuminate\Session\SessionManager::class],
  35.         'session.store'        => [\Illuminate\Session\Store::class, \Illuminate\Contracts\Session\Session::class],
  36.         'url'                  => [\Illuminate\Routing\UrlGenerator::class, \Illuminate\Contracts\Routing\UrlGenerator::class],
  37.         'validator'            => [\Illuminate\Validation\Factory::class, \Illuminate\Contracts\Validation\Factory::class],
  38.         'view'                 => [\Illuminate\View\Factory::class, \Illuminate\Contracts\View\Factory::class],
  39.     ] as $key => $aliases) {
  40.         foreach ($aliases as $alias) {
  41.             $this->alias($key, $alias);
  42.         }
  43.     }
  44. }

为alias属性赋值

$app核心类绑定

  1. /…/bootstrap/app.php
  2. /**
  3.  *核心类绑定
  4.  */
  5. $app->singleton(
  6.     Illuminate\Contracts\Http\Kernel::class,
  7.     App\Http\Kernel::class
  8. );
  9. $app->singleton(
  10.     Illuminate\Contracts\Console\Kernel::class,
  11.     App\Console\Kernel::class
  12. );
  13. $app->singleton(
  14.     Illuminate\Contracts\Debug\ExceptionHandler::class,
  15.     App\Exceptions\Handler::class
  16. );

调用bind函数

  1. //class Container
  2. public function singleton($abstract, $concrete = null)
  3. {
  4.     $this->bind($abstract, $concrete, true);
  5. }

对字符串类名进行默认回调函数绑定

  1. //class Container
  2. public function bind($abstract, $concrete = null, $shared = false)
  3. {
  4.     // If the factory is not a Closure, it means it is just a class name which is
  5.     // bound into this container to the abstract type and we will just wrap it
  6.     // up inside its own Closure to give us more convenience when extending.
  7.     if (! $concrete instanceof Closure) {
  8.         $concrete = $this->getClosure($abstract, $concrete);
  9.     }
  10.     $this->bindings[$abstract] = compact('concrete', 'shared');
  11. }

getClosure返回默认回调函数

  1. //class Container
  2. protected function getClosure($abstract, $concrete)
  3. {
  4.     return function ($container, $parameters = []) use ($abstract, $concrete) {
  5.         if ($abstract == $concrete) {
  6.             return $container->build($concrete);
  7.         }
  8.         return $container->make($concrete, $parameters);
  9.     };
  10. }

最终:返回$app

  1. /…/bootstrap/app.php
  2. return $app;


TAG标签:
本文网址:https://www.zztuku.com/index.php/detail-9062.html
站长图库 - 你知道Laravel的$this->app以及app()是怎么来的吗?
申明:如有侵犯,请 联系我们 删除。

评论(0)条

您还没有登录,请 登录 后发表评论!

提示:请勿发布广告垃圾评论,否则封号处理!!

    编辑推荐