Имеется магазин на yii2 advanced. Создан с полгода назад и все нажатия обрабатывались как и было задумано.
Пару месяцев назад прислали правки - сделал, проверил, все гут.
Потом еще были правки...
А 2 дня назад я, внеся еще правок, попробовал добавить товар в корзину, чтобы проверить работу оформления заказа, но корзина упорно показывала 0 товаров. Хотя в контроллере все прошло успешно и на странице появилось флеш-сообщение о том, что товар успешно добавлен.
После долгих попыток понять "что я сделал не так" и очередного нажатия на кнопку "добавить в корзину" товар добавился и я почти расслабился, но... нажав на "добавить в корзину" на другом товаре сообщение с успехом появилось, но товар в корзину не добавился.
Что очень примечательно, так это то, что в корзину добавляются, только некоторые товары, а после добавления одного товара не добавляется другой товар т.е. товар добаваляется только в пустую корзину и не больше одного наименования.
Все товары активны, с картинками, заполнены описания и мета-теги т.е. идентичны.
По цепочке действий выполняемых кодом сайта прошелся с var_dump и тоже все одинаково выводится до строчки сохранения в модели, что по идее должно гарантировать и одинаковое поведение, но...
Логи пусты, флеш-сообщение success, а где-то как-то что-то не срастается и не могу понять из-за чего и даже за что зацепиться.
Ниже привожу код, может быть вы найдете то, чего я в упор не вижу:
Экшен добавления:
/**
* @param $id
* @return mixed
* @throws NotFoundHttpException
*/
public function actionAdd($id)
{
if (!$product = $this->products->find($id)) {
throw new NotFoundHttpException('Запрашиваемая страница не существует.');
}
if (!$product->modifications) {
try {
$q = Yii::$app->request->post('AddToCartForm');
$this->service->add($product->id, null, $q['quantity']);
Yii::$app->session->setFlash('success', 'Товар успешно добавлен в корзину!');
return $this->redirect(Yii::$app->request->referrer);
} catch (\DomainException $e) {
Yii::$app->errorHandler->logException($e);
Yii::$app->session->setFlash('error', $e->getMessage());
}
}
$this->layout = 'blank';
$form = new AddToCartForm($product);
if ($form->load(Yii::$app->request->post()) && $form->validate()) {
try {
$this->service->add($product->id, $form->modification, $form->quantity);
return $this->redirect(['index']);
} catch (\DomainException $e) {
Yii::$app->errorHandler->logException($e);
Yii::$app->session->setFlash('error', $e->getMessage());
}
}
return $this->render('add', [
'product' => $product,
'model' => $form,
]);
}
Сервис добавления:
public function add($productId, $modificationId, $quantity): void
{
$product = $this->products->get($productId);
$modId = $modificationId ? $product->getModification($modificationId)->id : null;
$this->cart->add(new CartItem($product, $modId, $quantity));
}
CartItem делает для каждого добавленного товара запись о количестве единиц:
use shop\entities\Shop\Product\Modification;
use shop\entities\Shop\Product\Product;
class CartItem
{
private $product;
private $modificationId;
private $quantity;
public function __construct(Product $product, $modificationId, $quantity)
{
// if (!$product->canBeCheckout($modificationId, $quantity)) {
// throw new \RuntimeException('Вы выбрали большее количество, чем есть в наличии. может быть в другом месте эту ошибку вызывать чтобы не убивался сайт7 shop\cart\CartItem');
// }
$this->product = $product;
$this->modificationId = $modificationId;
$this->quantity = $quantity;
}
public function getId(): string
{
return md5(serialize([$this->product->id, $this->modificationId]));
}
public function getProduct(): Product
{
return $this->product;
}
public function getModificationId(): ?Modification
{
return $this->modificationId;
}
public function getModification(): ?Modification
{
if ($this->modificationId) {
return $this->product->getModification($this->modificationId);
}
return null;
}
public function getQuantity(): int
{
return $this->quantity ? $this->quantity : 1;
}
public function getPrice(): int
{
if ($this->modificationId) {
return $this->product->getModificationPrice($this->modificationId);
}
// Крупный опт
if ($this->product->price_roll && $this->product->roll_long && $this->quantity >= $this->product->roll_long) {
return $this->product->price_roll;
}
// Мелкий опт
if ($this->product->price_min && $this->product->min_long && $this->quantity >= $this->product->min_long) {
return $this->product->price_min;
}
return $this->product->price_new;
}
public function getCost(): int
{
return $this->getPrice() * $this->quantity;
}
public function plus($quantity)
{
return new static($this->product, $this->modificationId, $this->quantity + $quantity);
}
public function changeQuantity($quantity)
{
return new static($this->product, $this->modificationId, $quantity);
}
Сущность корзны:
use shop\cart\cost\calculator\CalculatorInterface;
use shop\cart\cost\Cost;
use shop\cart\storage\StorageInterface;
class Cart
{
private $storage;
private $calculator;
/**
* @var CartItem[]
* */
private $items;
public function __construct(StorageInterface $storage, CalculatorInterface $calculator)
{
$this->storage = $storage;
$this->calculator = $calculator;
}
/**
* @return CartItem[]
*/
public function getItems(): array
{
$this->loadItems();
return $this->items;
}
public function getAmount(): int
{
$this->loadItems();
return count($this->items);
}
public function add(CartItem $item): void
{
$this->loadItems();
foreach ($this->items as $i => $current) {
if ($current->getId() == $item->getId()) {
$this->items[$i] = $current->plus($item->getQuantity());
$this->saveItems();
return;
}
}
$this->items[] = $item;
$this->saveItems();
}
public function set($id, $quantity): void
{
$this->loadItems();
foreach ($this->items as $i => $current) {
if ($current->getId() == $id) {
$this->items[$i] = $current->changeQuantity($quantity);
$this->saveItems();
return;
}
}
throw new \DomainException('Item is not found.');
}
public function remove($id): void
{
$this->loadItems();
foreach ($this->items as $i => $current) {
if ($current->getId() == $id) {
unset($this->items[$i]);
$this->saveItems();
return;
}
}
throw new \DomainException('Item is not found.');
}
public function clear(): void
{
$this->items = [];
$this->saveItems();
}
public function getCost(): Cost
{
$this->loadItems();
return $this->calculator->getCost($this->items);
}
private function loadItems(): void
{
if ($this->items === null) {
$this->items = $this->storage->load();
}
}
private function saveItems(): void
{
$this->storage->save($this->items);
}
Хранилище корзины:
use shop\cart\CartItem;
interface StorageInterface
{
/**
* @return CartItem[]
*/
public function load(): array;
/**
* @param CartItem[] $items
*/
public function save(array $items): void;
}
Пожалуйста помогите разобраться.