Laravel:是否可以将Session注入为依赖项?

时间:2019-04-13 16:46:22

标签: php laravel session laravel-5

短版本

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

长期版本

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

  

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

reference

这对我来说很不方便。我一直在创建一个电子商务网站,其中购物车正在使用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的构造函数中。

class Cart
{
    private $items;

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

通过这种方式,Cart始终依赖于session ...,但是采用这种方法,Cart的依赖关系(即session)就不可能由Service provider解决,该访问无法访问会话(如上所述)。使用这种方法,必须使用new关键字才能实例化Cart

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用作类的依赖项(除了直接将其放置到构造函数中之外)?

任何建议将不胜感激。

1 个答案:

答案 0 :(得分:1)

对我来说,注入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));
        });
    }

我认为整个问题的症结在于无法直接在服务提供者中访问会话值,但是您可以访问使您可以访问所述值的服务。

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