首页 > 解决方案 > Laravel:是否可以将 Session 作为依赖项注入?

问题描述

短版

我想要实现的是session用作类的依赖项,最好是使用 Laravel 的服务提供者。那可能吗?

长版

最近发现session服务商无法访问,因为...

在 Laravel 中,会话由 StartSession 中间件处理,该中间件在所有服务提供者启动阶段之后执行

参考

这对我来说很不方便。我一直在创建一个购物车正在使用的电子商务网站session,并且session应该保留客户拿起的物品。

这是constructor购物车过去的样子……

class Cart
{
    private $items;

    public function __construct($items)
    {
        $this->items = $items;
    }
    //other functions...
}

而且,这里是AppServiceProvider.

class AppServiceProvider extends ServiceProvider
{
//boot

public function register()
{        
    $this->app->bind(Cart::class, function () {
        return new Cart(session('cart'));
    });
}

如前所述,session('cart')服务提供商无法访问。

所以,我session('cart')直接把Cart's 的构造函数。

class Cart
{
    private $items;

    public function __construct()
    {
        $this->items = session('cart');
    }
}

以这种方式,Cart总是依赖于session... 但是,使用这种方法,Cart的依赖关系(即session)不能用 来解决Service provider,它不能访问会话(如前所述)。使用这种方法,有必要使用new关键字来实例化Cart.

IE

class SomeController extends Controller
{
    private $cart;

    public function __construct(Cart $cart)
    {
        $this->cart = $cart;
    }

    public index()
    {
        $this->cart;
        //This will get null in its $items property,
        //because Service Providers can't access session

        $cart = new Cart();
        //This can get items from session()
    }
}

使用起来并不理想new Cart()。我想Cart作为依赖注入到控制器中。

有没有其他方法可以session用作类的依赖项(除了直接将其放入构造函数之外)?

任何建议将被认真考虑。

标签: phplaravelsessionlaravel-5

解决方案


对我来说,注入 Session 似乎是一个很常见的用例,而且缺少这方面的文档有点奇怪。

我已经对 Laravel 5.8 会话进行了一些实验,可能会为您提供解决方案。似乎您可以键入提示Illuminate\Session\Store类并使用它来检索您的数据。这将导致类似于以下类:

namespace App\Test;

use Illuminate\Session\Store;

class Cart
{
    /**
     * @var \Illuminate\Session\Store
     */
    private $session;

    public function __construct(Store $session)
    {
        $this->session = $session;
    }

    public function getItems(): array
    {
        return $this->session->get('cart') ?? [];
    }

    public function addItem(string $item): void
    {
        $this->session->push('cart', $item);
    }
}

此类由 Laravel 依赖容器自动解析。但是,如果您想自己执行此操作,您的服务提供商将类似于:

    public function register()
    {
        $this->app->bind(Cart::class, function (Container $container) {
            return new Cart($container->get(Store::class));
        });
    }

我认为这整件事的问题是不能直接在服务提供者中访问会话值,但是您可以访问使您可以访问所述值的服务。

您认为此解决方案适合您的用例吗?


推荐阅读