在laravel中重新注册服务提供商

时间:2015-03-25 17:37:02

标签: laravel laravel-4 inversion-of-control

我不确定我是否以正确的方式解决这个问题,但这是我正在尝试做的事情,如果有更好的方法请告诉我。

我正在使用从配置文件中提取一些数据的服务提供商。问题是,如果我在调用使用该服务提供程序的函数后使用Config::set更改其中一个设置,则不会更新。我认为这是因为我使用app->bind代替app->share,它每次都会重新实例化该类。这是我的代码:

服务提供商:

public function Register() {
  $app = $this->app;

  $app->bind('\path\to\MyInterface', function() use($app) {
     $server = $app['config']->get('myconfig.server');
     $client = $app['config']->get('myconfig.client');
     $key = $app['config']->get('myconfig.key');
     $version = $app['config']->get('myconfig.version');

     return new MyService(new Instance($server, $client, $key, $version));
  });

  $this->app->booting(function() {
     $loader = \Illuminate\Foundation\AliasLoader::getInstance();
     $loader->alias('MyServiceFacade', '\path\to\MyFacade');
  });
}

门面课程:

class MyServiceFacade extends Facade {

protected static function getFacadeAccessor() { return '\path\to\MyInterface'; }
}

测试路线:

 Route::get('test', function() {
  $nodes = MyServiceFacade::allNodes(); 


  \Config::set('myconfig.server', 'new server name');
  $nodes2 = MyServiceFacade::allNodes(); 

  var_dump($nodes->getContent());
  var_dump($nodes2->getContent());
}
);

我从两者得到了相同的结果。不应该使用更新配置,因为我正在制作一个新的控制器实例?

1 个答案:

答案 0 :(得分:0)

跳过以下更新2以获得答案

你的问题没有意义。在您的测试路线中,您要说

App::make('MyController');

这是你要求Laravel make MyController服务和/或类的实例。但是,您从未定义MyController服务和/或类。

您在此绑定\pathto\Interface标识符

$app->bind('\pathto\Interface', ...

并将MyService别名添加到此标识符

$loader->alias('MyService', '\pathto\Facade');

但是您无法在任何地方绑定或别名MyController标识符。您的代码示例中没有任何内容将MyController绑定到您绑定的服务。

因此,它并不是100%清楚你要问的是什么。

更新:您的问题仍然没有意义,我认为这种无意义掩盖是导致意外行为的原因。也就是说,你正在做一些"工作的事情,因为在PHP中并没有抱怨错误,但你认为幕后发生的事情并没有发生。

您已将MyService作为外观进行审核 - 但是,您还没有告诉我们外观访问者"字符串MyService Facade指向(通过其getFacadeAccessor方法)。此外,您似乎直接从该Facade类(new MyService)实例化一个类,这不是Laravel外观的工作方式。

更新2 :提供的代码示例仍然有点粗略,我怀疑它们并不能准确反映实际应用。评论的上下文是MyServiceFacade::allNodes是对外观的调用。但是,代码示例中定义的外观名为MyFacade,并且没有类MyServiceFacade。我将基于评论中提到的问题来解决问题,但根据我上面所看到的问题,问题仍然可能是服务提供商,服务和外墙的错误应用。

使用bind绑定服务可确保应用程序容器始终返回服务的新实例。我敢打赌,如果你尝试过类似下面的内容

$app = app();
$object = $app['\path\to\MyInterface'];

您发现每次都会重新实例化您的对象。向绑定闭包和/或服务类构造函数添加一些基本的var_dump调试是确认这一点的好方法。

然而,Laravel外观略有不同。从技术上讲,它们不是应用程序容器系统的一部分。 Facade是构建在应用程序容器之上的第二个系统。

除了为访问服务类提供方便的别名之外,外观实现还强制服务对象为单实例/单例,而不管您如何将其绑定到容器中。这发生在这里的基础外观类

#File: vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php
protected static function resolveFacadeInstance($name)
{
    if (is_object($name)) return $name;

    if (isset(static::$resolvedInstance[$name]))
    {
        return static::$resolvedInstance[$name];
    }

    return static::$resolvedInstance[$name] = static::$app[$name];
}

基础外观类在static::$resolvedInstance中保留实例缓存。对于StackExchange答案,Laravel如何到达这里的具体细节有点长,但我的Unraveling Laravel Facades文章(a longer series的一部分)是一个很好的起点。

这里的问题(同样,基于所提供的不完整信息)似乎是对外墙的误解。主要内容是外观总是迫使服务对象成为单身