readme.md

Корзина товаров

Идея и мысли спионерены вот тут, т.к. тот проект похоже загнулся.

Установка:

Установить пакет добавив в composer.json

~~~
...
"require": {
    ...
    "mavsan/laravel-cart": "^1.0"
}
~~~

или выполнив команду composer require mavsan/laravel-cart.

Добавить сервис провайдер и алиас в config/app.php (для Laravel >= 5.4 регистрация происходит автоматически):

[
    'providers' => [
        /*
         * Корзина
         */
        Mavsan\LaCart\Providers\CartProvider::class,
    ],
    
    'aliases' => [
        /*
         * Корзина
         */
        'Cart'  => Mavsan\LaCart\Facades\CartFacade::class,
        // по-желанию
        'CartDiscount' => Mavsan\LaCart\Facades\CartDiscountFacade::class,
    ],
];

Опубликовать конфигурацию и языковые файлы php artisan vendor:publish. В папку, с конфигурациями будет скопирован файл cart.php. В resources_path()/lang/vendor/cart будут скопированы языковые файлы.

Если во время установки пакета была прописана строка в aliases, тогда обращаться к корзине можно используя фасад Cart.

Добавление в корзину

Добавление в корзину осуществляется методом Cart::add(...).

$options, здесь и далее опции добавляемой записи, везде не обязательный параметр методов, например ['color' => 'blue', 'size' => 'L']). Влияет на rowID, это означает, что если будут добавлены два одинаковых товара (с одинаковым id), но разными опциями (один красный и маленький, другой синий и большой и т.д.), то в корзине будут созданы разные записи для этих товаров.

Cart::add($productID, $productTitle, $count, $price);

// или

Cart::add($productID, $productTitle, $count, $price, $options);

Так-же можно добавить в корзину передав массив:

Cart::add(['id' => 1, 'title' => 'Product Title', 'count' => 2, 'price' => 156, 'options' => ['color' => 'blue', 'size' => 'L']]);

// или

Cart::add(['id' => 1, 'title' => 'Product Title', 'count' => 2, 'price' => 156]);

Или, если модель продуктов реализует интерфейс Mavsan\LaCart\Interfaces\Buyable, добавить можно передав экземпляр этой модели. В данном варианте в элементе корзины так-же сохранится информация о классе, который использовался при добавлении товара в корзину (свойство model - будет храниться название класса).

Cart::add($model, $count, $options);

Cart::add($model, $count);

// количество добавленных единиц будет установлено в 1
Cart::add($model);

При любом из вышеперечисленных способов добавления, метод Cart::add() возвращает экземпляр добавленной записи - Mavsan\LaCart\Models\CartItem.

Добавление пачкой. Если по каким-то причинам необходимо добавить несколько товаров одновременно - необходимо передать в метод Cart::add() массив этих товаров. Каждый элемент такого массива должен быть или моделью, реализующей интерфейс Buyable (в данном случае кол-во добавляемых товаров будет = 1, для каждой такой модели), или массивом:

Cart::add([$product1, $product2, [
    'id' => '', 
    'title' => '', 
    'count' => '', 
    'price' => '',
    'options' => [...]]
]);

В данном случае метод Cart::add() вернет Collection элементами которой будут экземпляры CartItem соответственно добавляемым товарам.

Получение записей

Cart::getItems();

Вернет экземпляр Collection. Если в корзине оказались добавлены записи в количеством = 0 - они будут автоматически удалены.

Удаление из корзины

Для удаления элемента из корзины необходимо передать идентификатор строки CartItem::getRowID() или экземпляр CartItem в соответствующий метод:

Cart::removeItem($rowID);

Так-же удалить элемент из корзины можно обновив его, установив количество = 0.

Обновление данных в корзине

Необходимо получить CartItem $cartItem: Cart::getItem($rowID), изменить требуемые параметры, затем вызвать метод Cart::updateItem($oldRowID, CartItem $cartItem).

Старый $rowID здесь требуется на случай, если у обновляемого элемента корзины будет обновлено свойство от которого зависит rowID (сейчас это id и options) и будет сформирован новый rowID. В этом случае, если в корзине уже существует товар с таким rowID - он будет обновлен и у него будет изменено количество на старое + новое.

Так-же обновить данные можно используя модель, реализующую интерфейс Buyable или массив с новыми данными или просто обновить количество:

Cart::update($oldRowID, $buyableModel);

// обновит наименование
Cart::update($oldRowID, ['title' => 'newTitle']);
// обновит наименование и кол-во
Cart::update($oldRowID, ['count' => 10, 'title' => 'newTitle']);

// обновит количество
Cart::update($oldRowID, 5);

Если после обновления данных у записи количество будет = 0 - такая запись будет автоматически удалена из корзины.

Количество в корзине

Cart::count();

Очистка корзины

Cart::clear();

Были ли изменения в корзине

При добавлении, изменении, удалении товаров из корзины, а так-же при авто очистке от товаров с количеством = 0 и очистке - корзина изменяет свое состояние, проверить которое можно вызвав метод:

Cart::isChanged();

Это требуется, например для того, чтобы сохранить изменения в базу данных.

При этом необходимо иметь ввиду, что изменяя позицию в корзине таким образом, состояние корзины не изменится:

$item = Cart::getItem($itemRowID);
$item->set...();

Хотя содержимое элемента корзины изменится (т.к. передается по ссылке). Для недопущения этого - необходимо обновить элемент корзины, вызвав метод Cart::updateItem().

Сумма всего

Cart::totalPrice();

// форматированный вывод (number_format)
Cart::formatTotalPrice($decimals, $decimalSep, $thousandsSep);

Сумма всего с учетом скидки

В файле конфигурации настроить правила расчета скидок персональных для товаров и общей для корзины. Создать класс/функцию/замыкание, которое будет заполнять CartDiscount и прописать это в файле конфигурации (можно не создавать, а инициировать настройки скидок, скажем в сервис провайдере):

// если зарегистрирован фасад:
// сумма покупки от 1000 руб, скидка 5% или фиксированная - 200 руб.
CartDiscount::add(1000, 5, 200);

// если фасад не зарегистрирован
// сумма покупки от 5000 руб, скидка 10%, 500 руб.
App::make('cartDiscount')->add(5000, 10, 500);

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

// в настройках расчета скидки для корзины указать percent,discount (или наоборот, если используется смешанная схема и 
// вначале надо отнять фиксированную сумму, а затем уже процент)

// для покупки от 2000 до 4999,99 от суммы будет отниматься 500 руб 
App::make('cartDiscount')->add(2000, 0, 500);
// для покупки от 5000 и выше будет отниматься 10%
App::make('cartDiscount')->add(5000, 10, 0);

Получение итого с учетом скидки:

Cart::totalDiscount();
// форматированный вывод (number_format)
Cart::formatTotalDiscount($decimals, $decimalSep, $thousandsSep);

Округление

Для автоматического округления вывода необходимо вызвать метод Cart::setRound(true). После этого при вызове методов Cart::totalPrice() и Cart::totalDiscount() результат автоматически округлится.

Вызов Cart::setRound(true) не приведет к автоматическому округлению результатов расчета сумм для товаров, добавленных в корзину. Это сделано для повышения точности расчета, чтобы не терялись копейки. Чтобы округлялись и они необходимо вручную вызвать метод CartItem::setRound(true) для каждого добавленного в корзину:

Cart::getItems()->each(function($item, $rowID){
    $item->setRound(true);
    Cart::updateItem($rowID, $item);
});

Поиск

При необходимости найти что-то в добавленных в корзину записях можно воспользоваться методом Cart::search(closure):

Cart::add(1, 'Product1', 3, 20, ['color' => 'yellow']);
Cart::add(2, 'Product2', 5, 30, ['color' => 'white']);
Cart::add(3, 'Product3', 2, 5, ['color' => 'white']);

$result = $cart->search(function ($item, $index){
    /** @var \Mavsan\LaCart\Models\CartItem $item */
    return $item->getOptions()['color'] == 'white';
});

В замыкание передается два параметра. Первый - экземпляр CartItem, второй - rowID этого экземпляра.

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

Сохранение информации о модели

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

Если товар добавляется как модель и реализует интерфейс Buyable - информация о модели сохраняется автоматически при добавлении (см раздел “Добавление в корзину”).

Ручное добавление информации о модели:

Cart::setModel($rowID, $model);
  • $rowID идентификатор записи в которую сохраняется информация модели;
  • $model строковое название модели (Product::class, ‘App\Product’ и т.д.), либо экземпляр модели.

Во время сохранения информации о модели проверяется существование такого класса, если класса нет - будет выброшено исключение CartItemModelNotFoundException.

Получение модели

Для получения сохраненной ранее модели необходимо вызвать метод корзины Cart::getModel($rowID, $asObject = false).

  • $rowID идентификатор записи модель которой необходимо получить;
  • $asObject если true, то будет возвращен экземпляр объекта товара, модель должна содержать метод find($id), вызов которого вернет экземпляр объекта (если модель не была сохранена - будет вызвано исключение CartItemModelNotFoundException), если false, то будет возвращено строковое название модели.

Сохранение в базу данных

С корзиной идет миграция, путь к которой прописывается в сервис провайдере корзины. Т.е. все, что необходимо сделать после регистрации корзины в сервис-провайдере - выполнить php artisan migrate, после этого будет создана таблица с именем cart.

Сохранение выполняется в ручную, т.е. в нужный момент необходимо вызвать метод:

Cart::store($identifier, $updateIfExists = false);

где $identifier уникальный идентификатор (ид пользователя к примеру, на данный момент мультикорзина не реализована, не факт, что будет когда-либо реализована), $updateIfExists - обновлять ли, если запись с этим идентификатором уже есть в таблице. Сценарии:

  • $updateIfExists = false, будет выполнена проверка наличия записи с таким идентификатором. Если есть - будет вызвано исключение Mavsan\LaCart\Exceptions\CartAlreadyStoredException, если нет - будет выполнено сохранение.
  • $updateIfExists = true, если запись с этим идентификатором уже существует - она будет обновлена, если нет - вставлена.

Корзина после сохранения не очищается.

Получение корзины и базы данных

Как и сохранение - выполняется вручную методом Cart::restore($identifier). Если записи с указанным идентификатором не существует - ничего не произойдет, в противном случае к текущим записям в корзине будут добавлены восстановленные из базы данных, если какие-то записи совпадают - они буду перезаписаны теми, которые были сохранены с базе данных.

По окончании восстановления корзины - запись НЕ будет удалена из базы данных.

Удаление записи из базы данных

Для удаления записи из базы данных необходимо выполнить метод:

Cart::deleteCartFromDB($identifier);

Где лучше делать восстановление и сохранение корзины

По моему опыту лучше всего восстанавливать данные корзины из БД и сохранять в БД - в middleware, например, вот так:

class CartMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure                 $next
     *
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // если залогинен - восстановление корзины из БД
        if (Auth::check()) {
            Cart::restore(Auth::id());
        }

        $result = $next($request);

        // сохранение корзины в БД, если залогинен, переносить в terminate нельзя, т.к. не сохранится изменение в сессию
        if (Auth::check() && Cart::isChanged()) {
            Cart::store(Auth::id(), true);
            Cart::clear();
        }

        return $result;
    }
}

События

В процессе работы генерируются события:

  • cart.added запись добавлена в корзину, слушателю отправляется созданный экземпляр Mavsan\LaCart\Models\CartItem;
  • cart.updated запись обновлена в корзине, слушателю отправляется обновленный экземпляр Mavsan\LaCart\Models\CartItem;
  • cart.removed запись удалена из корзины, слушателю отправляется обновленный экземпляр Mavsan\LaCart\Models\CartItem;
  • cart.stored корзина сохранена в базу данных;
  • cart.restored корзина восстановлена из базы данных;
  • cart.deletedFromDB корзина удалена из базы данных;
  • cart.itemUpdated элемент корзины обновлен, слушателю отправляется экземпляр обновленного элемента корзины.

Исключения

\Mavsan\LaCart\Exceptions\CartInvalidRowIDException - при попытке получить запись добавленную в корзину, если искомой записи не существует.

\Mavsan\LaCart\Exceptions\CartItemModelNotFoundException

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

InvalidArgumentException - при установке не верного количества элементов в корзине, строка к примеру.

Mavsan\LaCart\Exceptions\CartAlreadyStoredException - если при сохранении в базу данных оказалось, что запись с таким идентификатором уже есть.

Описание

Корзина товаров для laravel

Конвейеры
0 успешных
0 с ошибкой