hypef 七、配置文件的使用

 关于配置文件先解释下命令行的实现。

bin/hyperf.php先加载config/container.php,通过容器获取$application,调用$application->run()。

#/config/container.php
$container = new Container((new DefinitionSourceFactory(true))());

if (! $container instanceof \Psr\Container\ContainerInterface) {
    throw new RuntimeException('The dependency injection container is invalid.');
}
return ApplicationContext::setContainer($container);

#/bin/hyperf.php
require BASE_PATH . '/vendor/autoload.php';

// Self-called anonymous function that creates its own scope and keep the global namespace clean.
(function () {
    Hyperf\Di\ClassLoader::init();
    /** @var Psr\Container\ContainerInterface $container */
    $container = require BASE_PATH . '/config/container.php';

    $application = $container->get(Hyperf\Contract\ApplicationInterface::class);
    $application->run();
})();

#Hyperf\Di\Definition\DefinitionSourceFactory
public function __invoke()
    {
        $configDir = $this->baseUri . '/config';

        $configFromProviders = [];
        if (class_exists(ProviderConfig::class)) {
            $configFromProviders = ProviderConfig::load();
        }

        $serverDependencies = $configFromProviders['dependencies'] ?? [];
        if (file_exists($configDir . '/autoload/dependencies.php')) {
            $definitions = include $configDir . '/autoload/dependencies.php';
            $serverDependencies = array_replace($serverDependencies, $definitions ?? []);
        }

        return new DefinitionSource($serverDependencies);
    }

container.php初始化容器,$resolvedEntries中设置默认对应内容。其get方法可获取对应实现类或设置对应类。

#Hyperf\Di\Container  
public function __construct(Definition\DefinitionSourceInterface $definitionSource)
    {
        $this->definitionSource = $definitionSource;
        $this->definitionResolver = new ResolverDispatcher($this);
        // Auto-register the container.
        $this->resolvedEntries = [
            self::class => $this,
            PsrContainerInterface::class => $this,
            HyperfContainerInterface::class => $this,
        ];
    }
public function get($name)
    {
        // If the entry is already resolved we return it
        if (isset($this->resolvedEntries[$name]) || array_key_exists($name, $this->resolvedEntries)) {
            return $this->resolvedEntries[$name];
        }
        return $this->resolvedEntries[$name] = $this->make($name);
    }

每个模块的配置中设置有依赖、配置、注释等。其配置的位置在每个模块对应的composer.json。

# Hyperf\Framework\ConfigProvider
class ConfigProvider
{
    public function __invoke(): array
    {
        return [
            'dependencies' => [
                ApplicationInterface::class => ApplicationFactory::class,
                StdoutLoggerInterface::class => StdoutLogger::class,
            ],
            'annotations' => [
                'scan' => [
                    'paths' => [
                        __DIR__,
                    ],
                ],
            ],
        ];
    }
}

#Hyperf\ExceptionHandler\ConfigProvider
class ConfigProvider
{
    public function __invoke(): array
    {
        return [
            'dependencies' => [
                FormatterInterface::class => DefaultFormatter::class,
            ],
            'listeners' => [
                ExceptionHandlerListener::class,
            ],
            'annotations' => [
                'scan' => [
                    'paths' => [
                        __DIR__,
                    ],
                ],
            ],
        ];
    }
}

#Hyperf\Config
class ConfigProvider
{
    public function __invoke(): array
    {
        return [
            'dependencies' => [
                ConfigInterface::class => ConfigFactory::class,
            ],
            'aspects' => [
                ValueAspect::class,
            ],
            'listeners' => [
                RegisterPropertyHandlerListener::class,
            ],
            'annotations' => [
                'scan' => [
                    'paths' => [
                        __DIR__,
                    ],
                ],
            ],
        ];
    }
}
#vendor/hyperf/framework/composer.json
"extra": {
        "branch-alias": {
            "dev-master": "2.2-dev"
        },
        "hyperf": {
            "config": "Hyperf\\Framework\\ConfigProvider"
        }
    }

#vendor/hyperf/exception-handler/composer.json
"extra": {
        "branch-alias": {
            "dev-master": "2.2-dev"
        },
        "hyperf": {
            "config": "Hyperf\\ExceptionHandler\\ConfigProvider"
        }
    }

#vendor/hyperf/config/composer.json
 "extra": {
        "branch-alias": {
            "dev-master": "2.2-dev"
        },
        "hyperf": {
            "config": "Hyperf\\Config\\ConfigProvider"
        }
    }

根据hyper.php调用,配置文件加载后应该有Hyperf\Contract\ApplicationInterface::class对应的实现类或者通过make函数处理获取对应的实现类。

初始化$container = new Container((new DefinitionSourceFactory(true))())将 DefinitionSourceFactory类作为方法使用,调用__invoke()。

DefinitionSourceFactory::__invoke()通过ProviderConfig::load()加载/composer.lock。composer.lock将上述各个模块的composer.json合并到一个文件,作为json文件解析。

#Hyperf\Config\ProviderConfig
public static function load(): array
    {
        if (! static::$providerConfigs) {
            $providers = Composer::getMergedExtra('hyperf')['config'] ?? [];
            static::$providerConfigs = static::loadProviders($providers);
        }
        return static::$providerConfigs;
    }

所以/vendor/autoload.php运行之后,各个模块入口的接口类对应的实体类都能通过容器获取到。

所有配置文件在Hyperf\Config\ConfigFactory中加载入项目,该类在其他模块中用于获取配置。

#Hyperf\Config\ConfigFactory 
public function __invoke(ContainerInterface $container)
    {
        $configPath = BASE_PATH . '/config/';
        $config = $this->readConfig($configPath . 'config.php');
        $autoloadConfig = $this->readPaths([BASE_PATH . '/config/autoload']);
        $merged = array_merge_recursive(ProviderConfig::load(), $config, ...$autoloadConfig);
        return new Config($merged);
    }

以下为配置文件中hyperf.config的加载流程。在Hyperf\Devtool\VendorPublishCommand::execute()中设置,最终在Symfony\Component\Console\Application::run()中使用。

# Hyperf\Devtool\VendorPublishCommand
protected function execute(InputInterface $input, OutputInterface $output)
    {
      ……
        $provider = Arr::get($extra, 'hyperf.config');
        $config = (new $provider())();

        $publish = Arr::get($config, 'publish');
      ……
    }

#Symfony\Component\Console\Command\Command
public function run(InputInterface $input, OutputInterface $output)
{
……
if ($this->code) {
            $statusCode = ($this->code)($input, $output);
        } else {
            $statusCode = $this->execute($input, $output);

            if (!\is_int($statusCode)) {
                throw new \TypeError(sprintf('Return value of "%s::execute()" must be of the type int, "%s" returned.', static::class, get_debug_type($statusCode)));
            }
        }
……
}

#Symfony\Component\Console\Application
protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
{
……
 if (null === $this->dispatcher) {
            return $command->run($input, $output);
        }
……
}

 public function doRun(InputInterface $input, OutputInterface $output)
{
……
 $this->runningCommand = $command;
        $exitCode = $this->doRunCommand($command, $input, $output);
        $this->runningCommand = null;
……
}
public function run(InputInterface $input = null, OutputInterface $output = null)
{
……
 try {
            $exitCode = $this->doRun($input, $output);
        } catch (\Exception $e) {
    ……
    }
……
}

所以接下来的问题是config模块的加载时间和我好奇的linster和exception配置文件的使用。

不过留在以后再研究,还是先把整个框架学完。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lsswear

感谢大佬打赏 q(≧▽≦q)

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值