Silex PHP - 如何在 register() 之后使用来自自定义服务提供商的动态密钥填充$app


Silex PHP - How to populate $app with dynamic keys from custom service provider after register()

我是 m1/vars 的开发人员,它是 Silex 的配置加载器服务提供商,我想知道让我的库更有用的是如何在注册服务并处理$app->register()的辅助参数后将密钥动态加载到$app中。

例如,这是它目前的工作方式:

应用.php:

$app->register(new M1'Vars'Provider'Silex'VarsServiceProvider('example.yml'), [
    'vars.path' => __DIR__,
    'vars.options' => [
        // options here
    ]
]);
$app['vars.merge']();

VarsServiceProvider.php:

$app['vars'] = function ($app) {
    return new Vars($this->entity, $this->createOptions($app));
};
$app['vars.merge'] = $app->protect(function() use ($app) {
    static $initialized = false;
    if ($initialized) {
        return;
    }
    $initialized = true;
    foreach ($app['vars']->toDots(false) as $key => $value) {
        $app[$key] = $value;
    }
});

这基本上是它懒惰地从配置文件(example.yml)加载东西 - 所以当访问它加载$app['vars'] - 所以$app['vars.options']将可用,因为它已经在register()的第二个参数中定义。 $app['vars.merge']将数据从$app['vars']加载到$app,例如,如果您定义了:

例子.yml

monolog.logfile: %dir%/../../app/logs/app/dev.log

$app['vars.merge']()后,您可以从$app['monolog.logfile']加载上述内容,而不是$app['vars']['monolog.logfile']

我的目标是摆脱$app['vars.merge'],因为它对我来说似乎不对,而且看起来有点笨拙,但问题是$app['vars.options']$app['vars.path']必须可供$app['vars']使用,我不想在打电话之前打电话给$app['vars'] $app['vars.monolog.logfile']

任何想法,如果它没有意义,我会尝试解释更多?

谢谢。

如果我猜对了,你为什么不直接从你的提供者那里打电话给app['vars.merge']呢?实际上,您可以避免使用 vars.merge 函数,而只需在寄存器函数中调用 for each 即可。

为了使您的提供程序对 Silex 更友好,我可能会在您的提供程序的引导方法中实现 foreach。

此方法的签名很简单:public function boot(Application $app);和文档可能我认为这是您可能想要的:

引导应用程序。

注册所有服务后调用此方法 并且应该用于"动态"配置(每当 必须请求服务)。

因此,您的引导方法应如下所示:

<?php
// ...
class VarsServiceProvider implements ServiceProviderInterface
{
    // ...
    public function boot(Application $app)
    {
        foreach ($app['vars']->toDots(false) as $key => $value) {
            $app[$key] = $value;
        }
    }
}

我对引导方法的主要担忧是,一旦应用程序启动,参数就会加载,这在某些情况下可能有点太晚了,你应该对此做一些研究(就是这种情况,然后只是把foreach放在register方法中)。

第二次尝试

看到这些选项都不适用于您的用例,那么像这样定义您的服务怎么样?

<?php
// Service Provider
$app['vars'] = function ($app) {
    $instance = new Vars($this->entity, $this->createOptions($app));
    foreach ($instance->toDots(false) as $key => $value) {
        $app[$key] = $value;
    }
    return $instance;
};

希望有帮助。