Laravel `between app->bind` 和 `app->singleton` 的区别?

标签 laravel laravel-4 singleton facade

我一直在试图弄清楚 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 之间的适当行为和 singletonfoo分别打印一次和两次。但是,如果我们像这样通过外观运行它:
Data::set('test', 'test');
Data::set('cheese', 'cheese');

当它是一个单例时,我希望这两个 testcheese可用,当它是 bind我不确定我希望通过立面获得什么,但似乎没有区别。

它是把所有东西都当作 singleton 的外观。 ?

最佳答案

你的问题有点令人困惑,没有人可以回答的所有信息,但这是一个令人困惑的话题,所以不要难过。这是一个可以帮助你更好地理解的纲要,并提出你想问的问题(另外,我对 Laravel 很陌生,所以我可能不了解这些)

  • make方法用于实例化对象。当你说 App::make('Data')你告诉 Laravel 从类 Data 中实例化一个对象.
  • 第 1 条有一个警告。如果您调用 make 并且已经绑定(bind)了字符串 Data到服务容器中的东西 , Laravel 将返回该服务。这可能意味着 Laravel 实例化了一个新的服务对象,也可能意味着 Laravel 返回一个服务单例
  • Laravel 是否返回单例或服务实例取决于 服务如何绑定(bind)
  • 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/

    相关文章:

    css - laravel 元素无法加载 Font Awesome 样板

    datetime - 拉拉维尔 : display personal format of timestamps fields

    javascript - 使用来自 ajax 的数据在 Laravel 中创建输入

    laravel-4 - Composer 未下载包的 src 目录

    Php:单例VS全静态类?什么时候用什么?

    php - Laravel:验证大于零的数字失败

    php - 属于through方法

    php - 拉维尔 4 : Get ID of last attached record

    c++ - 如何避免这种类似单例的设计模式?

    java - 我们如何确保在集群环境中有一个类的单个实例