我一直在试图弄清楚 app->bind
之间的区别和 app->singleton
在 Laravel 中设置服务提供者时。我的印象是,如果我注册 singleton
每次调用它都会返回相同的对象实例 vs bind
这将是一个新实例。
这是一个简单的例子:
正面:
use Illuminate\Support\Facades\Facade;
class DataFacade extends Facade
{
protected static function getFacadeAccessor() {
return 'Data';
}
}
服务提供者:
use Illuminate\Support\ServiceProvider;
class DataServiceProvider extends ServiceProvider
{
public function register() {
$this->app->singleton('Data', function() {
return new Data;
});
}
}
类(class):
class Data
{
public $data = [];
public function get($key)
{
return isset($this->data[$key]) ? $this->data[$key] : null;
}
public function set($key, $val)
{
$this->data[$key] = $val;
}
}
如果我们这样做:
$instance = App::make('Data');
$instance->set('foo', 'foo');
$instance2 = App::make('Data');
echo $instance->get('foo');
echo $instance2->get('foo');
然后运行,我们将看到
bind
之间的适当行为和 singleton
与 foo
分别打印一次和两次。但是,如果我们像这样通过外观运行它:Data::set('test', 'test');
Data::set('cheese', 'cheese');
当它是一个单例时,我希望这两个
test
和 cheese
可用,当它是 bind
我不确定我希望通过立面获得什么,但似乎没有区别。它是把所有东西都当作
singleton
的外观。 ?
最佳答案
你的问题有点令人困惑,没有人可以回答的所有信息,但这是一个令人困惑的话题,所以不要难过。这是一个可以帮助你更好地理解的纲要,并提出你想问的问题(另外,我对 Laravel 很陌生,所以我可能不了解这些)
make
方法用于实例化对象。当你说 App::make('Data')
你告诉 Laravel 从类 Data
中实例化一个对象. make
并且已经绑定(bind)了字符串 Data
到服务容器中的东西 , Laravel 将返回该服务。这可能意味着 Laravel 实例化了一个新的服务对象,也可能意味着 Laravel 返回一个服务单例 make
方法不绑定(bind)任何东西bind
绑定(bind)。方法,在容器类上定义,方法原型(prototype)如下public function bind($abstract, $concrete = null, $shared = false)
$shared
范围?如果这是真的,您的服务将返回一个单例。如果为 false,您的服务将返回实例。 singleton
方法是一种绑定(bind)服务的方法 回复:#7,这里是
singleton
的定义#File: vendor/laravel/framework/src/Illuminate/Container/Container.php
public function singleton($abstract, $concrete = null)
{
$this->bind($abstract, $concrete, true);
}
在上面的示例中,您正在绑定(bind)服务
Data
进入容器。使用前导案例服务名称会导致问题 -- data
会是更好的选择。如果您的 register
由于某种原因没有调用方法,make
仍将使用您的全局类 Data
实例化一个对象关于您的外观——外观是实例/单一性的额外层。这是外观类使用
getFacadeAccessor
中的字符串的方法。从静态调用返回一个对象#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];
}
所以,门面使用
$app[$name];
从容器中获取服务。这是ArrayAccess
, 所以如果我们看一下 offsetGet
的定义public function offsetGet($key)
{
return $this->make($key);
}
我们看到
ArrayAccess
结束对 make
的调用.这意味着如果您没有绑定(bind)服务,外观访问将实例化一个对象。如果您将服务绑定(bind)为单例/共享服务,则外观访问将返回该单例。如果您将服务绑定(bind)为非单例/共享服务,则外观访问将实例化一个新对象。然而 , Facade 本身将存储它在
static::$resolvedInstance
中实例化的任何对象,并且将来对外观的调用将返回相同的实例。这意味着 Facade 访问引入了第二个单例实现。绑定(bind)为单例的服务将存储在应用程序对象中,通过外观访问的服务将作为单例存储在 Facade
上。类(class)。
关于Laravel `between app->bind` 和 `app->singleton` 的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25797594/