简体   繁体   English

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

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

I'm the developer for m1/vars , which is a config loader service provider for Silex, what I want to know to make my library more useful is how to go about dynamically loading keys into $app after registering the service and dealing with the secondary parameters of $app->register() . 我是开发商M1 /增值经销商 ,这是一个Silex的配置装载机服务提供商,我想知道让库更有用的是如何去动态加载项为$app注册服务和处理后$app->register()辅助参数。

For example this is how it currently works: 例如,这是当前的工作方式:

app.php: app.php:

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

$app['vars.merge']();

VarsServiceProvider.php: 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;
    }
});

What this basically does is it loads the stuff from the config file ( example.yml ) lazily -- so when accessing $app['vars'] it loads -- so the $app['vars.options'] will be available as it has already been defined in the second parameter of register() . 这基本上是从配置文件( example.yml )懒惰地加载东西-因此在访问$app['vars']它会加载-因此$app['vars.options']将作为它已经在register()的第二个参数中定义。 $app['vars.merge'] loads the data from $app['vars'] into $app , for example if you defined: $app['vars.merge']将数据从$app['vars'] $app['vars.merge']加载到$app ,例如,如果您定义:

example.yml example.yml

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

After $app['vars.merge']() you could then load the above from $app['monolog.logfile'] instead of $app['vars']['monolog.logfile'] $app['vars.merge']()您可以从$app['monolog.logfile']而不是$app['vars']['monolog.logfile']

What I'm aiming for is getting rid of $app['vars.merge'] as it doesn't seem right to me and seems a bit hacky but the problem is the $app['vars.options'] and $app['vars.path'] have to be available for $app['vars'] and I don't want to have to call $app['vars'] before I can call $app['vars.monolog.logfile'] . 我想要的是摆脱$app['vars.merge']因为它对我来说似乎不正确,看起来有些hacky,但问题是$app['vars.options']$app['vars.path']必须可用于$app['vars'] ,在我可以调用$app['vars.monolog.logfile']之前,我不想调用$app['vars'] $app['vars.monolog.logfile']

Any ideas, if it doesn't make sense I'll try and explain a bit more? 有什么想法,如果没有意义的话,我会尝试解释更多吗?

Thanks. 谢谢。

If I got you right, why don't you just call app['vars.merge'] directly from your provider? 如果我说对了,为什么不直接从您的提供商那里直接调用app['vars.merge'] In fact, you could avoid the vars.merge function and just call the for each inside the register function. 实际上,您可以避免使用vars.merge函数,而只需在register函数中为每个函数调用。

In order to make your provider more Silex friendly I would probably implement the foreach inside the boot method of your provider. 为了使您的提供程序对Silex更友好,我可能会在提供程序的boot方法内部实现foreach。

The signature from this method is simple: public function boot(Application $app); 此方法的签名很简单: public function boot(Application $app); and the docs may me think that this is what you probably want: 而文档可能让我认为这可能就是您想要的:

Bootstraps the application. 引导应用程序。

This method is called after all services are registered and should be used for "dynamic" configuration (whenever a service must be requested). 在注册所有服务之后,将调用此方法,并且应将其用于“动态”配置(每当必须请求服务时)。

So your boot method should look like: 因此,您的启动方法应如下所示:

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

My main concern with the boot method is that the parameters will be loaded once the application is booted which may be a little too late in some circumstances, you should do some research about that (it that's the case then just put the foreach inside the register method). 我对启动方法的主要担心是,一旦启动应用程序,参数将被加载,在某些情况下可能为时已晚,您应该对此进行一些研究(在这种情况下,只需将foreach放入register方法)。

Second attempt 第二次尝试

Seeing that none of this options are valid for your use case, what about defining your service like so? 看到所有这些选项都不适合您的用例,那么像这样定义您的服务呢?

<?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;
};

Hope that helps. 希望能有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM