Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 12.10.2017 13:35:37

Session store not set on request.

Добрый день.
У меня есть сервис CartService

PHP
    /**
     * @var \Illuminate\Session\Store
     */
    
protected $session;

    
/**
     * @var Guard
     */
    
protected $auth;

    
/**
     * @var ProductVariation
     */
    
protected $variation;

    
/**
     * @var Cart
     */
    
protected $cart;

    
/**
     * @var SettingService
     */
    
protected $setting;

    
/**
     * @var Request
     */
    
protected $request;

    
/**
     * CartService constructor.
     * @param Request $request
     * @param Guard $auth
     * @param ProductVariation $variation
     * @param Cart $cart
     */
    
public function __construct(Request $requestGuard $authProductVariation $variationCart $cart)
    {
        
$this->request $request;
        
$this->session $request->session();
        
$this->auth $auth;
        
$this->variation $variation;
        
$this->setting = new SettingService();
        
$this->cart $this->setCart($cart);
    }

Так вот, если создавать обьект этого сервиса в методе контроллера, то все четко работает как надо, но если создавать обьект этого сервиса в конструкторе контроллера, то вылазиет ошибка

(1/1) RuntimeException
Session store not set on request.
in Request.php (line 399)
at Request->session()
in CartService.php (line 53)
at CartService->__construct(object(Request), object(SessionGuard), object(ProductVariation), object(Cart))
in FrontendCartController.php (line 38)
at FrontendCartController->__construct(object(Request), object(SessionGuard), object(ProductVariation), object(Cart))

Нагугли на ларавел ньюс ком что начиная с лары 5.3 обьект реквеста в контроллере конструктора нельзя создавать. Окей, но почему то у меня в других контроллерах (в конструкторе) я спокойно (инжектю?) через лок контейнер без всяких ошибок. Почему тут он ругается?
Вот собственно сам код контроллера

PHP
    /**
     * @var CartService
     */
    
protected $cart;

    
/**
     * @var Guard
     */
    
protected $auth;

    
/**
     * @var ProductVariation
     */
    
protected $variation;

    
/**
     * FrontendCartController constructor.
     * @param Request $request
     * @param Guard $auth
     * @param ProductVariation $variation
     * @param Cart $cart
     */
    
public function __construct(Request $requestGuard $authProductVariation $variationCart $cart)
    {
        
parent::__construct();
        
$this->auth $auth;
        
$this->cart = new CartService($request$auth$variation$cart);;
        
$this->variation $variation;
    }

Не в сети

#2 12.10.2017 16:23:11

Re: Session store not set on request.

А зачем ты это изначально делаешь? Есть ведь глобальный помощник session() для работы с сессией.

Изменено AlexeyMezenin (12.10.2017 16:24:46)

Не в сети

#3 12.10.2017 17:40:11

Re: Session store not set on request.

А это будит нормально? Все же внедряют обьект в конструктор.

Не в сети

#4 12.10.2017 17:42:29

Re: Session store not set on request.

Нормально. Не видел в реальных приложениях, чтобы кто-то так делал. session() читаемый, тестировать функционал легко и пр., зачем его внедрять в конструктор?

Не в сети

#5 12.10.2017 18:19:45

Re: Session store not set on request.

  1. зачем его внедрять в конструктор?

Ну я 2 — 3 раза видел что так делают, и тоже стал делать) Спасибо. С хелпером отлично работает.

Не в сети

#6 15.10.2017 07:48:55

Re: Session store not set on request.

И всеже с хелпером не работает. Хелпер возвращает пустой результат.
Перенес посредника StartSession из $middlewareGroups в $middleware, все стало работать. Вопрос в том — на сколько это критично? Сейчас использую лару 5.4, покрошется ли приложение при обновлении?
Я где то на SO в комментариях видел что вы Алексей писали что все отлично работает после этих действий. Так ли это? Я имею ввиду, не пришлось ли менять все обратно?

Не в сети

#7 15.10.2017 09:22:59

Re: Session store not set on request.

И всеже с хелпером не работает. Хелпер возвращает пустой результат.

Покажи код пожалуйста. Где именно пробуешь сохранить данные и где пробуешь получить?

Перенес посредника StartSession из $middlewareGroups в $middleware, все стало работать. Вопрос в том — на сколько это критично? Сейчас использую лару 5.4, покрошется ли приложение при обновлении? Я где то на SO в комментариях видел что вы Алексей писали что все отлично работает после этих действий.

Давай на ты. Я помню что-то подобное, но не скажу что будет при очередном обновлении. Хорошая идея - не модифицировать такие вещи.

Сессия нормально работает из коробки почти во всех версиях (в некоторых минорных были проблемы). У тебя свежая установка или менял что-то?

Изменено AlexeyMezenin (15.10.2017 09:23:15)

Не в сети

#8 15.10.2017 11:18:14

Re: Session store not set on request.

  1. Покажи код пожалуйста. Где именно пробуешь сохранить данные и где пробуешь получить?

Полностью весь сервис, для понимания. Нсли вернуть сессию обратно, то код будит работать не правильно в функции code() где берется код из сессии. Когда пробую получить код из сессии, он возвращает null и создается все время новая корзина.

PHP
namespace App\Services;

use 
App\Cart;
use 
App\ProductVariation;

class 
CartService extends Service
{
    
/**
     * @var ProductVariation
     */
    
protected $variation;

    
/**
     * @var Cart
     */
    
protected $cart;

    
/**
     * @var SettingService
     */
    
protected $setting;

    
/**
     * @var mixed
     */
    
protected $code;

    
/**
     * CartService constructor.
     * @param ProductVariation $variation
     * @param Cart $cart
     */
    
public function __construct(ProductVariation $variationCart $cart)
    {
        
parent::__construct();
        
$this->variation $variation;
        
$this->setting = new SettingService();
        
$this->cart $cart;
        
$this->code $this->code();
    }

    
/**
     * Add products to cart
     *
     * @param $productId
     * @param int $quantity
     * @param array $variations
     */
    
public function add($productId$quantity 1, array $variations = [])
    {
        
$cart $this->gerCart();

        if(
count($variations)) {
            
$this->setVariation($productId$variations);
        }

        
$cart->products()->attach($productId,[
            
'product_variation_id' => isset($this->variation->id) ? $this->variation->id 0,
            
'quantity' => $quantity
        
]);
    }

    
/**
     * Load products in cart and return cart / products
     *
     * @param bool $withModel
     * @param array $fields
     * @return mixed
     */
    
public function products($withModel true, array $fields = ['*'])
    {
        
$cart $this->cart->with([
            
'cartProducts',
            
'cartProducts.product' => function($q) use($fields){
                
$q->select($fields);
            },
            
'cartProducts.variation',
            
'cartProducts.variation.combinations'])->whereCode($this->code)->first();

        if(
$withModel) {
            return 
$cart;
        }

        return 
$cart->cartProducts;
    }

    
/**
     * Remove product from cart
     *
     * @param $id
     * @return bool
     */
    
public function remove($id)
    {
        if(isset(
$id) && is_numeric($id) && $id !== 0) {
            
$variation $this->variation->whereHas('product', function($q) use($id){
                
$q->where('id'$id);
            })->
first();

            
$cart $this->gerCart();

            if(
$variation) {
                return 
$cart->products()->wherePivot('product_variation_id'$variation->id)->detach($id);
            } else {
                return 
$cart->products()->detach($id);
            }
        }

        return 
false;
    }

    
/**
     * Get code or create new one and cart
     *
     * @return mixed
     */
    
public function code()
    {
        
$code $this->session->get('cart.code');

        if(
is_null($code)) {
            return 
$this->createNewCart();
        }

        return 
$code;
    }

    
/**
     * Get cart
     *
     * @return mixed
     */
    
public function getCart()
    {
        return 
$this->cart->whereCode($this->code)->first();
    }

    
/**
     * Find product variation by it attributes
     *
     * @param $id
     * @param array $attributes
     */
    
private function setVariation($id, array $attributes)
    {
        
$this->variation $this->variation->whereHas('combinations', function($q) use($attributes) {
            
$q->whereIn('product_variation_combination.attribute_id'$attributes);
        })->
where('product_id'$id)->first();
    }

    
/**
     * Create a new cart instance
     *
     * @return mixed
     */
    
public function createNewCart()
    {
        
$cart $this->cart->create([
            
'code' => strtoupper(str_random(12)),
            
'user_id' => $this->auth->id() ? $this->auth->id() : Null,
            
'shop_id' => $this->setting->get('shop.id'),
            
'lang_id' => $this->session->get('lang'$this->setting->get('parameters.general.language_id'))
        ]);

        
$this->session->put('cart'$cart->toArray());

        return 
$cart->code;
    }
}

А это уже контроллер

PHP
use App\Cart;
use 
App\ProductVariation;
use 
Illuminate\Http\Request;
use 
App\Services\CartService;

class 
FrontendCartController extends FrontendBaseController
{
    
/**
     * @var Cart
     */
    
protected $cart;

    
/**
     * @var ProductVariation
     */
    
protected $variation;

    
/**
     * FrontendCartController constructor.
     * @param ProductVariation $variation
     * @param Cart $cart
     */
    
public function __construct(ProductVariation $variationCart $cart)
    {
        
parent::__construct();
        
$this->cart = new CartService($variation$cart);
    }

    
/**
     * Add product to cart
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    
public function addToCart(Request $request)
    {
        try
        {
            
// We filter request data, as quantity or variation
            // may not be in request
            
$data = [
                
'id' => (int)$request->product,
                
'quantity' => $request->quantity ? (int)$request->quantity 1,
                
'variation' => (array)$request->variation
            
];
            
$this->cart->add($data['id'], $data['quantity'], $data['variation']);

            return 
response()->json(view('frontend.ajax.cart', [
                
'products' => $this->cart->products()
            ])->
render(), 200);
        }
        catch (\
Throwable $t)
        {
            return 
response()->json(['error ' $t->getMessage() . $t->getFile() . $t->getLine()], 422);
        }
    }

    
/**
     * Show cart
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    
public function showCart(Request $request)
    {
        return 
response()->json(view('frontend.ajax.cart', [
            
'cart' => $this->cart->products()
        ])->
render());
    }

    
/**
     * Remove product from cart
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    
public function removeFromCart(Request $request)
    {
        try
        {
            
$this->cart->remove($request->product);

            return 
response()->json('success'200);
        }
        catch (\
Throwable $t)
        {
            return 
response()->json(['error ' $t->getMessage() . $t->getFile() . $t->getLine()], 422);
        }
    }
}
  1. Давай на ты

Окей

  1. Сессия нормально работает из коробки почти во всех версиях (в некоторых минорных были проблемы). У тебя свежая установка или менял что-то?

Я ничего не менял. Устанавливал еще где то в августе.

  1. php artisan -V

Laravel Framework 5.4.28
Сейчас пока нет возможности обновить до 5.5 тк на сервере php 5.6

Изменено Testuser123 (15.10.2017 11:23:24)

Не в сети

#9 15.10.2017 11:34:16

Re: Session store not set on request.

Раз у тебя сервис использует сессию при его создании, внедряй сервис не в конструкторе контроллера, а в методах, где он используется.

Или попробуй избавиться от:

$this->code = $this->code();

И в коде вместо $this->code, используй геттер $this->code() (луше, кстати, переименовть в getCode()).

Изменено AlexeyMezenin (15.10.2017 11:39:41)

Не в сети

#10 17.10.2017 16:11:28

Re: Session store not set on request.

AlexeyMezenin, придется так сделать. Спасибо!

Не в сети

Подвал раздела