PHP / laravel Добавление элемента в сеанс не сохранено

вчера я начал свой первый проект laravel. но у меня проблема, которую я не могу понять.

Я пытаюсь создать корзину для покупок, и я отслеживаю использование объекта сеанса laravel с моей собственной оболочкой. код выглядит так:

class SessionController extends Controller
{
 static function getSessionData($key = null, $data = null)
    {
        if ($data === null)
        {
            return Session::get($key);
        }

        else
        {
            return Session::get($key, $data);
        }
    }

    static function allSessionData()
    {
        return Session::all();
    }

    static function putSessionData($key = null, $data)
    {
        if ($key === null)
        {
            Session::put($data);
        }
        else
        {
            Session::put($key, $data);
        }
    }

    static function has($key)
    {
        return Session::has($key);
    }  

Теперь внутри моего класса ShoppingCart я создал поле $instance, в котором хранятся данные корзины покупок, или создается пустая корзина покупок, если она еще не в сеансе. код выглядит так:

class ShoppingCart extends Model
{
    public $id;
    public $session;
    private $sessionName = 'shoppingcart';
    private $instance;
    public $cartItems;

    protected $connection = 'mysql2';
    protected $table = 'shoppingcart';
    protected $primaryKey = 'Id';   


    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);
        $this->cartItems = [];
    }

    private function getOrCreateSession()
    {
        if (SessionController::has($this->sessionName))
        {
            $this->instance = SessionController::getSessionData($this->sessionName);
        }

        else
        {
            SessionController::putSessionData($this->sessionName, $this);
            $this->instance = SessionController::getSessionData($this->sessionName);
        }
    }

    function addCartItem($productId, $qty = 1)
    {
        $this->getOrCreateSession();
        $cartItem = $this->createCartitem($productId, $qty);
        $content = $this->getContent();

        if ($existingCartitem = $this->alreadyInCart($cartItem)) {
            $existingCartitem->qty += $cartItem->qty;
        } else {
            array_push($content, $cartItem);
        }
    }

    function createCartItem($productId, $qty)
    {
        $cartItem = CartItem::fromId($this->instance->id, $productId, $qty);
        $cartItem->associate($this->instance->id);

        return $cartItem;
    }

    private function alreadyInCart($cartItem)
    {
        $alreadyInCart = FALSE;

        foreach ($this->instance->cartItems as $item) {
            if ($item->productId == $cartItem->productId) {
                return $item;
            }
        }

        return $alreadyInCart;
    }

    //returns current shoppingcart contents.
    private function getContent()
    {
       return $this->instance->cartItems;
    }
}

Теперь внутри метода addCartItem я пытаюсь вставить новый элемент cartitem в массив, используя array_push(), но var_dump()-ing сеанса впоследствии показывает, что сеанс не содержит вновь добавленного элемента. Однако, если я var_dump(), $content до и после метода array_push, я вижу, что он добавлен.

Я думал, что PHP передаст сеанс по ссылке, но, похоже, мне что-то здесь не хватает.

Что я делаю не так?

Заранее спасибо.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
0
362
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вам нужно будет вернуть сеанс по ссылке, т.е.

static function &getSessionData($key = null, $data = null)

и используйте его, получив ссылку, например:

$myVariable = &SessionController::getSessionData($this->sessionName);

Цитата из документы:

Returning by reference is useful when you want to use a function to find to which variable a reference should be bound. Do not use return-by-reference to increase performance. The engine will automatically optimize this on its own. Only return references when you have a valid technical reason to do so. To return references, use this syntax:

<?php
class foo {
    public $value = 42;

    public function &getValue() {
        return $this->value;
    }
}

$obj = new foo;
$myValue = &$obj->getValue(); // $myValue is a reference to $obj->value, which is 42.
$obj->value = 2;
echo $myValue;                // prints the new value of $obj->value, i.e. 2.
?>

Спасибо за ваш ответ, к сожалению, изменения все еще не сохранены после изменения моего кода так, как вы сказали, что я должен. Что-то не так с передачей определенного сеансового элемента по ссылке? (например, это плохая практика или ..?)

Mathijs 14.08.2018 15:54

@Mathijs, можете ли вы отредактировать свой вопрос и добавить способ, который вы пробовали?

Lajos Arpad 14.08.2018 20:00

Ваш ответ был правильным. Пришлось добавить и в getContent()-метод. Теперь это работает. Спасибо!

Mathijs 15.08.2018 08:39

хотя мне все еще интересно, правильно ли это делать? Считается ли это хорошей практикой или нет?

Mathijs 15.08.2018 08:48

@Mathijs, возвращающие ссылки сами по себе, не являются хорошей или плохой практикой, это возможности. Что делает эту практику хорошей или плохой, так это контекст. Если вы видите любую возможность того, что эти ссылки будут неправильно обработаны серверным кодом, то это плохая практика. Если вы не видите такой опасности, то это хорошая практика. Если вы не видите другой возможности, тогда это необходимая практика. В общем, не стоит возвращать ничего по ссылке без уважительной причины. В нашем случае я думаю, что вы можете достичь своей цели более элегантным способом.

Lajos Arpad 15.08.2018 16:51

@Mathijs Вы можете переместить все, что напрямую изменяет значения сеанса, в класс SessionController и обернуть их вокруг методов. Это защитит вас от решения одной и той же задачи несколько раз, а любую необходимость может решить класс.

Lajos Arpad 15.08.2018 16:53

На самом деле вы никогда не сохраняете (не сохраняете) данные в Session.

Попробуйте использовать фасад Session, выполнив что-нибудь вроде Session::put('new.item' , $cartItem).

Затем вы можете получить элемент в своем контроллере через: Session::get('new.item').

Спасибо за ответ, но не передавайте сеанс по ссылке, убедитесь, что добавление чего-либо к $instance, например array_push($instance, $cartItem), - это то же самое, что сказать Session::put('shoppingcart', $cartItem)?

Mathijs 14.08.2018 15:53

К сожалению, в этом случае это работает не так, потому что вы используете диспетчер сеансов Laravel (это оболочка над глобалом $_SESSION), поэтому вы должны играть по их правилам, а не напрямую ссылаться на глобальный сеанс :)

Matt Wohler 14.08.2018 16:25

Я только что построил простую корзину для покупок совсем недавно (хотя и на Lumen), возможно, это поможет вам: gist.github.com/MattWohler/1917e0d92b391536b6f2bbaff90923edBasket.php - это оболочка для сеанса. Итак, в моем случае моя тележка - это сеанс, а ваша - таблица в БД. Надеюсь, поможет.

Matt Wohler 14.08.2018 16:33

Другие вопросы по теме