Laravel app-> bind和app-> singleton之间的区别? [英] Laravel Difference `between app->bind` and `app->singleton`?

查看:667
本文介绍了Laravel app-> bind和app-> singleton之间的区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试找出在Laravel中设置服务提供者时app->bindapp->singleton之间的区别.我的印象是,如果我注册一个singleton,则每次调用该对象时都会返回该对象的相同实例vs bind,这将是一个新实例.

I've been trying to figure out what the difference between app->bind and app->singleton are when setting up a service provider in Laravel. I was under the impression that if I register an singleton it would return the same instance of the object each time it was called vs bind which would be a new instance.

这是一个简单的例子:

门面:

use Illuminate\Support\Facades\Facade;

class DataFacade extends Facade
{
    protected static function getFacadeAccessor() { 
        return 'Data';
    }
}

ServiceProvider:

ServiceProvider:

use Illuminate\Support\ServiceProvider;

class DataServiceProvider extends ServiceProvider
{
    public function register() {
        $this->app->singleton('Data', function() {
            return new Data;
        });
    }
}

班级:

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

如果我们做类似的事情:

If we do something like:

$instance = App::make('Data');
$instance->set('foo', 'foo');

$instance2 = App::make('Data');

echo $instance->get('foo');
echo $instance2->get('foo');

运行,我们将看到bindsingleton之间的适当行为,其中foo分别打印了一次,然后打印了两次.但是,如果我们像这样通过立面运行它:

And run that we will see the appropriate behavior between bind and singleton with foo being printed out once and then twice respectively. However if we run it through the facade like so:

Data::set('test', 'test');
Data::set('cheese', 'cheese');

当它是单例时,我希望testcheese都可用,而当它是bind时,我不确定我希望通过立面获得什么,但是似乎有没什么

When it's a singleton I would expect both test and cheese to be available and when it's a bind I'm not sure what I would expect to be available via the facade, but it seems like there is no difference.

是将所有内容都视为singleton的立面吗?

It's the facade treating everything as a singleton?

推荐答案

您的问题有点令人困惑,并且没有人可以回答的所有信息,但这是一个令人困惑的主题,因此不要感到难过.这是一个摘要,可以帮助您更好地理解,并提出您想问的问题(而且,我对Laravel还是陌生的,所以我可能对这些不太满意)

Your question is a little confusing and doesn't have all the information for someone to answer, but it's a confusing topic, so don't feel bad. Here's a rundown that may help you better understand, and ask the question you wanted to ask (also, I'm newish to Laravel, so I may be off base with these)

  1. make方法用于实例化对象.当您说App::make('Data')时,您是在告诉Laravel从类Data实例化一个对象.

  1. The make method is used to instantiate objects. When you say App::make('Data') you're telling Laravel to instantiate an object from the class Data.

第1个警告,如果您调用make 并且已经将字符串Data绑定到服务容器中的某个东西,Laravel将会返回该服务.这可能意味着Laravel实例化了一个新的服务对象,或者可能意味着Laravel返回了一个服务单例.

There's a caveat to number 1. If you call make and have already bound the string Data to something in the service container, Laravel will return the service instead. This may mean Laravel instantiates a new service object, or it may mean Laravel returns a service singleton

Laravel是否为服务返回单例或实例取决于服务的绑定方式

Whether or not Laravel returns a singleton or an instance for a service depends on how the service was bound

make方法不绑定任何内容

您可以使用以下方法原型public function bind($abstract, $concrete = null, $shared = false)

You bind services with the application object's bind method, defined on the container class with the following method prototype public function bind($abstract, $concrete = null, $shared = false)

看到第三个$shared参数吗?如果是这样,您的服务将返回单例.如果为假,则您的服务将返回实例.

See that third $shared parameter? If that's true your service will return a singleton. If it's false your service will return instances.

应用程序对象的singleton方法是用于绑定服务的方法

回复:#7,这是singleton

#File: vendor/laravel/framework/src/Illuminate/Container/Container.php
public function singleton($abstract, $concrete = null)
{
    $this->bind($abstract, $concrete, true);
}

在上面的示例中,您将服务Data绑定到了容器中.使用首字母大写的服务名称会引起问题-data是一个更好的选择.如果由于某些原因未调用您的register方法,则make仍将使用全局类Data

In your examples above you're binding the service Data into the container. Using a leading case service name is going to cause problems -- data would be a better choice. If your register method isn't called for some reason, make will still instantiate an object with your global class Data

关于您的Facade-Facade是实例/单一性的额外一层.这是Facade类使用getFacadeAccessor中的字符串从静态调用返回对象的方法

Regarding your Facade -- a Facade is an extra layer of instance/singleton-ness. Here's the method where the facade class uses the string from getFacadeAccessor to return an object from a static call

#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

So, a facade uses $app[$name]; to grab a service from the container. This is ArrayAccess, so if we look at the definition of offsetGet

public function offsetGet($key)
{
    return $this->make($key);
}

我们看到ArrayAccess包装了对make的调用.这意味着,如果您没有绑定服务,则外观访问将实例化一个对象.如果您将服务绑定为单例/共享服务,则外观访问将返回该单例.如果您将服务绑定为非单例/共享服务,则外观访问将实例化一个新对象.

We see ArrayAccess wraps a call to make. This means if you have no bound service, facade access will instantiate an object. If you have the service bound as a singleton/shared service, facade access will return that singleton. If you have the service bound as not a singleton/shared service, facade access will instantiate a new object.

如何,Facade本身会将其实例化的任何对象存储在static::$resolvedInstance内部,以后对Facade的调用将返回该实例.这意味着Facade访问引入了第二个单例实现.绑定为单例的服务将存储在应用程序对象上,通过立面访问的服务将作为单例存储在Facade类上.

HOWEVER, the Facade itself will store any object it instantiates inside static::$resolvedInstance, and future calls to the facade will return this same instance. This means Facade access introduces a second singleton implementation. A service bound as a singleton will be stored on the application object, a service accessed via a facade will be stored as a singleton on the Facade class.

这篇关于Laravel app-> bind和app-> singleton之间的区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆