Yii framework - корзина (LavrikShoppingCart), на сессиях


Во время написания интернет-магазина на yii framework, столкнулся с проблемой реализации корзины на YII. Сразу нашел в интернете расширение shoppingCart, которое мне НЕ понравилось.

  • Во-первых, оно неправильно считало скидки. Эту проблему я устранил, путем правки кода, но это отдельная история и в целом моё отношение к shoppingCart не изменило.
  • Во-вторых, его не удобно дорабатывать и расширять.

Взялся я за написание своего "велосипеда" корзины. Работает расширение тоже на сессиях, его легче (на мой взгляд) доработать и расширить функционал. В отличие от shoppingCart, всё сидит в одном файле.

Скачать исходник можно здесь.

Для подключения нужно:

1) Создаем в директории /protected/components/ новую папку -  LavrikShoppingCart.

2) Заливаем в неё скачанных файл - LavrikShoppingCart.php.

3) Подключаем библиотеку в файле /protected/config/main.php следующим кодом:

'components'=>array(

        'LavrikShoppingCart' =>   //  Козина
        array(
            'class' => 'application.components.LavrikShoppingCart.LavrikShoppingCart', 
            ),
       
        // ...  ещё какие-то подключения
         
),

Теперь можно использовать в любом месте на сайте например следующим способом:

Yii::app() -> LavrikShoppingCart -> put($item, $count);

В библиотеку заложены только те функции которые когда-либо мне были нужны. При необходимости она легко дописывается. Принцип работы понятен любому, кто хоть немного понимает в PHP.

Теперь кратко пробегусь по функционалу:

1) Метод put($position, $count) используется для занесения товара в корзину. Первый параметр - объект модели товара (в моем случае это модель Items. Цена товара должна быть параметром price. Если цена товара сидит в другом параметре, то необходимо заменить его в начале файла LavrikShoppingCart.php). Используем метод так:

$item = Items::model()->findByPk(100014);
Yii::app() -> LavrikShoppingCart -> put($item, $count);

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

2) Метод UpdateCountInBascet($id, $count) изменяет количество конкретной позиции в корзине. Первый параметр - id позиции,  второй параметр, естественно количество этой позиции.

3) Метод getSumToPosition($id) возвращает сумму конкретной позиции.

4) Метод DelFromBasket($id) удаляет позицию из сессии (а вернее отключает). Данный метод проверяет - если отключены все позиции, то сессия автоматически удаляется.

Yii::app() -> LavrikShoppingCart -> DelFromBasket(100014);

5) Ну и конечно-же в любой момент можно обратиться к любому параметру корзины:

echo 'В корзине - '.Yii::app() -> LavrikShoppingCart -> count_in_basket.' позиций(я)<br>';
echo 'На сумму - '.Yii::app() -> LavrikShoppingCart -> sum.' руб.<br>';
echo 'В корзине - '.Yii::app() -> LavrikShoppingCart -> count_of_different_products.' наименований(е)<br>';

6) Получить массив с полным списком покупок можно следующим способом:

$ShoppingList = Yii::app() -> LavrikShoppingCart -> getShoppingList();

Если корзина пустая, метод вернёт false.

7) Если вас интересует какая-то конкретная позиция, то отправляем в вышеописанную функцию id интересующего товара:

$ShoppingList = Yii::app() -> LavrikShoppingCart -> getShoppingList(100014);

Если позиция отсутствует, во функция возвратит false.

8) Для проверки наличия конкретной позиции в корзине, есть метод isset_in_basket($id):

if (Yii::app() -> LavrikShoppingCart -> isset_in_basket($id))
	{
	echo 'Позиция '.$id.' находится в корзине.';
	}
	else
	{
	echo 'Позиции '.$id.' в корзине нет.';
	}

Чтобы проверить, есть ли что-нибудь вообще в корзине, можно использовать последний метод без параметра.

9) Отчистить корзину можно методом clear();

Yii::app() -> LavrikShoppingCart -> clear();

Что-бы увидеть весь основной функционал приведу тестовый action для тестирования целиком:

public function actionLavrikShoppingCart()
	{
	
	//  Проверяю содержимое корзины в начале:
	echo 'В корзине - '.Yii::app() -> LavrikShoppingCart -> count_in_basket.' позиций(я)<br>';
	echo 'На сумму - '.Yii::app() -> LavrikShoppingCart -> sum.' руб.<br>';
	echo 'В корзине - '.Yii::app() -> LavrikShoppingCart -> count_of_different_products.' наименований(е)<br>';
	
	
	//Заношу несколько позиций:
	
	// 2 позиции с id=100012
	$item = Items::model()->findByPk(100012);
	Yii::app() -> LavrikShoppingCart -> put($item, 2);
	
	// 4 позиции с id=100014
	$item2 = Items::model()->findByPk(100014);
	Yii::app() -> LavrikShoppingCart -> put($item2, 4);

	
	//  Проверяю содержимое корзины теперь:
	echo '<hr>';
	echo 'В корзине - '.Yii::app() -> LavrikShoppingCart -> count_in_basket.' позиций(я)<br>';
	echo 'На сумму - '.Yii::app() -> LavrikShoppingCart -> sum.' руб.<br>';
	echo 'В корзине - '.Yii::app() -> LavrikShoppingCart -> count_of_different_products.' наименований(е)<br>';
	
	
	/*
	$basket[ номер ]['id'] 		- уникальный идентификатор позиции в сессии (он-же id товара в базе)
	$basket[ номер ]['count'] 	- количество данного товара
	$basket[ номер ]['price'] 	- цена товара
	$basket[ номер ]['vkl'] 		- флаг отключающий товар в сессии
	*/
	// Получаю массив с полным списком покупок:
	echo '<hr>';
	$ShoppingList = Yii::app() -> LavrikShoppingCart -> getShoppingList();
	echo '<pre>';
	print_r($ShoppingList);
	echo '</pre>';
	
	
	
	// Получаю массив покупок конкретной позиции (например id = 100014)
	echo '<hr>';
	$ShoppingList = Yii::app() -> LavrikShoppingCart -> getShoppingList(100014);
	echo '<pre>';
	print_r($ShoppingList);
	echo '</pre>';
	
	Yii::app() -> LavrikShoppingCart -> clear();
	}

Вот и весь скромный, но достаточный на мой взгляд, функционал библиотеки.

Скачать исходник можно здесь.

Принимаю любую критику.

 


Тэги:

Комментарии: 23

Прокомментировать »

 
 
Sider
23.09.2013
 

посмотрим....

howard
24.09.2013
 

Bascet -> Basket Если цена товара сидит в другом параметре, то необходимо заменить его на строчке 125 и 136 файла Ну зачем же так усложнять, а вынести в свойство, не и в конфиге менять на свое? Приведите уже тогда к горбатому регистру count_in_basket count_of_different_products

Lavrik
25.09.2013
 

howard - ваш отзыв заставил меня значительно переписать приложение. Если вы это читаете, значит статья уже исправлена с учетом нового приложения. Ваше пожелание учтено тоже.

ElisDN
26.09.2013
 

Весьма странный интерфейс. ID из сессии, ID из базы... – неполиморфно. Лишняя головная боль. Ручной recalculation() – весьма странно. Эффективнее добавить геттер. Возможно с кэшированием.

Lavrik
27.09.2013
 

ElisDN - спасибо за комментарий. Действительно, с двумя id было неудобно. Переписал расширение, оно стало проще и понятнее. Но насчет добавления геттера, наверное не соглашусь. Мне хотелось-бы сделать расширение более простым для доработки, а это скорее усложнит его.

ElisDN
1.10.2013
 

«Сразу нашел в интернете расширение shoppingCart... в нем много бесполезных, запутанных, вызывающих друг-друга функций и мало действительно нужных» – добро пожаловать в мир разумного программирования. Ваше расширение должно стремиться стать таким же.

Lavrik
2.10.2013
 

ElisDN - видел много разумного софта, shoppingCart вряд ли можно положить на полочку "Разумное программирование"... Приведите мне хоть одно преимущество данной библиотеки и её запутанности... Я НЕ говорю что моя версия данного расширения идеальна или просто хорошая, но и не считаю shoppingCart такой... Именно поэтому мне интересно выслушать любую критику и отталкиваясь от неё, дорабатывать расширение.

Sergei
6.10.2013
 

вроде сносно...

TwiX
14.10.2013
 

Много раз использовал shoppingCart - все куда более понятно. "Много бесполезных, запутанных, вызывающих друг-друга функций" как раз таки во благо расширяемости. Вы просто не разобрались и написали свой велосипед)

Andrey
6.01.2015
 

Здравствуйте уважаемый Lavrik. Хотел поинтересоваться, как лучше поступить с минимальными изменениями вашего расширения, если цены на мои у слуги и на товары хранятся в отдельной таблице (один к одному) и связаны внешним ключем?

LAVRIK
6.01.2015
 

Andrey - для этого вам необходимо на 65 строчке поменять $pr = $this->name_row_prise; на $pr = $this->"др.таблица"->name_row_prise; Сработает это только если у вас правильно настроены rules у данного объекта.

Andrey
28.01.2015
 

И еще момент, сделал, как вы сказали, у меня есть связь 1:1 'price' , которая прописана в relations моего класса Product и используется пока при отображения товара. В таблице mc_price, к которой поставлена связь, поле для цены имеет название "NAME" поэтому в $name_row_prise я написал name Сделал как вы сказали (через связь): $pr = $this->price->name_row_prise; И словил CException: Не определено свойство "Product.".

LAVRIK
28.01.2015
 

Andrey - скорее всего ошибка в rules. Проверьте в отдельном экшене работоспособность связи с продуктов таблицей цен.

Andrey
28.01.2015
 

Разобрался с ценами, сделал: $price = $position->price->NAME; Но вот с редиректом неясно, почему ругается, пробовал оставить только редирект и он отрабатывается, с фрагментом Yii::app()->LavrikShoppingCart->put($model, $count); перед ним происходит описанная выше ошибка(

Andrey
28.01.2015
 

Попробовал оставить метод put пустым: public function put($position = false, $count = false) { } Ошибка все равно вылазит, ищу дальше..

LAVRIK
28.01.2015
 

Andrey - о каком редиректе идет речь? Где он находится?

Andrey
28.01.2015
 

Оставил такой кусок кода: class LavrikShoppingCart { public function init(){} public function recalculation() {} public function put($position, $count) {} } И все равно ошибка вылезает, в чем может быть причина?

LAVRIK
28.01.2015
 

Andrey - это говорит о том, что ошибка не в avrikShoppingCart.

Andrey
28.01.2015
 

При этом функция отрабатывается, если ничего не удалять, просто ругается на редирект, спасибо, буду дальit искать причину.

Andrey
28.01.2015
 

Поменяйте кодировку компонента на UTF-8 без BOM, это все исправило!!

LAVRIK
28.01.2015
 

Andrey - либо ещё вариант решения (если кому-то принципиален "UTF-8 без BOM") - обернуть вызов метода PUT в ob_start(); и ob_end_clean();

Andrey
25.04.2015
 

Добрый день. Данная библиотека имеет возможность 1. удаления из корзины одного товара (у которого может быть разное количество естественно) 2. можно ли изменять кол-во для одного товара (меняем например в корзине и делаем refresh)

LAVRIK
4.05.2015
 

Andrey - чам вас не устраивает метод UpdateCountInBascet($id, $count)?

 

Прокомментировать

 
 
Сообщение *
 
Проверочный код *
 
 
 
Яндекс.Метрика