reliq/darryldecode-cart

Laravel 购物车

dev-main 2024-06-15 23:22 UTC

This package is auto-updated.

Last update: 2024-09-15 23:57:57 UTC


README

Build Status Total Downloads License

Laravel 框架的购物车实现

快速部分演示

演示: https://shoppingcart-demo.darrylfernandez.com/cart

演示的 Git 仓库:https://github.com/darryldecode/laravelshoppingcart-demo

安装

通过 Composer 安装此包。

对于 Laravel 5.1~: composer require "darryldecode/cart:~2.0"

对于 Laravel 5.5, 5.6, 或 5.7~, 9

composer require "darryldecode/cart:~4.0"composer require "darryldecode/cart"

配置

  1. 打开 config/app.php 并将此行添加到您的 Service Providers 数组中。
Darryldecode\Cart\CartServiceProvider::class
  1. 打开 config/app.php 并将此行添加到您的 Aliases 中
  'Cart' => Darryldecode\Cart\Facades\CartFacade::class
  1. 可选配置文件(如果您计划完全控制,则很有用)
php artisan vendor:publish --provider="Darryldecode\Cart\CartServiceProvider" --tag="config"

如何使用

快速使用示例

// Quick Usage with the Product Model Association & User session binding

$Product = Product::find($productId); // assuming you have a Product model with id, name, description & price
$rowId = 456; // generate a unique() row ID
$userID = 2; // the user ID to bind the cart contents

// add the product to cart
\Cart::session($userID)->add(array(
    'id' => $rowId,
    'name' => $Product->name,
    'price' => $Product->price,
    'quantity' => 4,
    'attributes' => array(),
    'associatedModel' => $Product
));

// update the item on cart
\Cart::session($userID)->update($rowId,[
	'quantity' => 2,
	'price' => 98.67
]);

// delete an item on cart
\Cart::session($userID)->remove($rowId);

// view the cart items
$items = \Cart::getContent();
foreach($items as $row) {

	echo $row->id; // row ID
	echo $row->name;
	echo $row->qty;
	echo $row->price;
	
	echo $item->associatedModel->id; // whatever properties your model have
        echo $item->associatedModel->name; // whatever properties your model have
        echo $item->associatedModel->description; // whatever properties your model have
}

// FOR FULL USAGE, SEE BELOW..

使用方法

重要说明!

默认情况下,购物车有一个默认的 sessionKey,用于存储购物车数据。这也作为购物车的唯一标识符,您可以用它来将购物车绑定到特定用户。要覆盖此默认 session Key,您只需在调用任何其他方法之前简单调用 \Cart::session($sessionKey) 方法即可!。

示例

$userId // the current login user id

// This tells the cart that we only need or manipulate
// the cart data of a specific user. It doesn't need to be $userId,
// you can use any unique key that represents a unique to a user or customer.
// basically this binds the cart to a specific user.
\Cart::session($userId);

// then followed by the normal cart usage
\Cart::add();
\Cart::update();
\Cart::remove();
\Cart::condition($condition1);
\Cart::getTotal();
\Cart::getSubTotal();
\Cart::getSubTotalWithoutConditions();
\Cart::addItemCondition($productID, $coupon101);
// and so on..

下面有更多示例

向购物车添加商品: Cart::add()

您可以通过几种方式向购物车添加商品,下面是其中一些

/**
 * add item to the cart, it can be an array or multi dimensional array
 *
 * @param string|array $id
 * @param string $name
 * @param float $price
 * @param int $quantity
 * @param array $attributes
 * @param CartCondition|array $conditions
 * @return $this
 * @throws InvalidItemException
 */

 # ALWAYS REMEMBER TO BIND THE CART TO A USER BEFORE CALLING ANY CART FUNCTION
 # SO CART WILL KNOW WHO'S CART DATA YOU WANT TO MANIPULATE. SEE IMPORTANT NOTICE ABOVE.
 # EXAMPLE: \Cart::session($userId); then followed by cart normal usage.
 
 # NOTE:
 # the 'id' field in adding a new item on cart is not intended for the Model ID (example Product ID)
 # instead make sure to put a unique ID for every unique product or product that has it's own unique prirce, 
 # because it is used for updating cart and how each item on cart are segregated during calculation and quantities. 
 # You can put the model_id instead as an attribute for full flexibility.
 # Example is that if you want to add same products on the cart but with totally different attribute and price.
 # If you use the Product's ID as the 'id' field in cart, it will result to increase in quanity instead
 # of adding it as a unique product with unique attribute and price.

// Simplest form to add item on your cart
Cart::add(455, 'Sample Item', 100.99, 2, array());

// array format
Cart::add(array(
    'id' => 456, // inique row ID
    'name' => 'Sample Item',
    'price' => 67.99,
    'quantity' => 4,
    'attributes' => array()
));

// add multiple items at one time
Cart::add(array(
  array(
      'id' => 456,
      'name' => 'Sample Item 1',
      'price' => 67.99,
      'quantity' => 4,
      'attributes' => array()
  ),
  array(
      'id' => 568,
      'name' => 'Sample Item 2',
      'price' => 69.25,
      'quantity' => 4,
      'attributes' => array(
        'size' => 'L',
        'color' => 'blue'
      )
  ),
));

// add cart items to a specific user
$userId = auth()->user()->id; // or any string represents user identifier
Cart::session($userId)->add(array(
    'id' => 456, // inique row ID
    'name' => 'Sample Item',
    'price' => 67.99,
    'quantity' => 4,
    'attributes' => array(),
    'associatedModel' => $Product
));

// NOTE:
// Please keep in mind that when adding an item on cart, the "id" should be unique as it serves as
// row identifier as well. If you provide same ID, it will assume the operation will be an update to its quantity
// to avoid cart item duplicates

更新购物车上的商品: Cart::update()

更新购物车上的商品非常简单

/**
 * update a cart
 *
 * @param $id (the item ID)
 * @param array $data
 *
 * the $data will be an associative array, you don't need to pass all the data, only the key value
 * of the item you want to update on it
 */

Cart::update(456, array(
  'name' => 'New Item Name', // new item name
  'price' => 98.67, // new item price, price can also be a string format like so: '98.67'
));

// you may also want to update a product's quantity
Cart::update(456, array(
  'quantity' => 2, // so if the current product has a quantity of 4, another 2 will be added so this will result to 6
));

// you may also want to update a product by reducing its quantity, you do this like so:
Cart::update(456, array(
  'quantity' => -1, // so if the current product has a quantity of 4, it will subtract 1 and will result to 3
));

// NOTE: as you can see by default, the quantity update is relative to its current value
// if you want to just totally replace the quantity instead of incrementing or decrementing its current quantity value
// you can pass an array in quantity value like so:
Cart::update(456, array(
  'quantity' => array(
      'relative' => false,
      'value' => 5
  ),
));
// so with that code above as relative is flagged as false, if the item's quantity before is 2 it will now be 5 instead of
// 5 + 2 which results to 7 if updated relatively..

// updating a cart for a specific user
$userId = auth()->user()->id; // or any string represents user identifier
Cart::session($userId)->update(456, array(
  'name' => 'New Item Name', // new item name
  'price' => 98.67, // new item price, price can also be a string format like so: '98.67'
));

从购物车中删除商品: Cart::remove()

从购物车中删除商品非常简单

/**
 * removes an item on cart by item ID
 *
 * @param $id
 */

Cart::remove(456);

// removing cart item for a specific user's cart
$userId = auth()->user()->id; // or any string represents user identifier
Cart::session($userId)->remove(456);

获取购物车上的商品: Cart::get()

/**
 * get an item on a cart by item ID
 * if item ID is not found, this will return null
 *
 * @param $itemId
 * @return null|array
 */

$itemId = 456;

Cart::get($itemId);

// You can also get the sum of the Item multiplied by its quantity, see below:
$summedPrice = Cart::get($itemId)->getPriceSum();

// get an item on a cart by item ID for a specific user's cart
$userId = auth()->user()->id; // or any string represents user identifier
Cart::session($userId)->get($itemId);

获取购物车内容和数量: Cart::getContent()

/**
 * get the cart
 *
 * @return CartCollection
 */

$cartCollection = Cart::getContent();

// NOTE: Because cart collection extends Laravel's Collection
// You can use methods you already know about Laravel's Collection
// See some of its method below:

// count carts contents
$cartCollection->count();

// transformations
$cartCollection->toArray();
$cartCollection->toJson();

// Getting cart's contents for a specific user
$userId = auth()->user()->id; // or any string represents user identifier
Cart::session($userId)->getContent($itemId);

检查购物车是否为空: Cart::isEmpty()

/**
* check if cart is empty
*
* @return bool
*/
Cart::isEmpty();

// Check if cart's contents is empty for a specific user
$userId = auth()->user()->id; // or any string represents user identifier
Cart::session($userId)->isEmpty();

获取购物车的总数量: Cart::getTotalQuantity()

/**
* get total quantity of items in the cart
*
* @return int
*/
$cartTotalQuantity = Cart::getTotalQuantity();

// for a specific user
$cartTotalQuantity = Cart::session($userId)->getTotalQuantity();

获取购物车的小计: Cart::getSubTotal()

/**
* get cart sub total
*
* @return float
*/
$subTotal = Cart::getSubTotal();

// for a specific user
$subTotal = Cart::session($userId)->getSubTotal();

获取不带条件的购物车小计: Cart::getSubTotalWithoutConditions()

/**
* get cart sub total with out conditions
*
* @param bool $formatted
* @return float
*/
$subTotalWithoutConditions = Cart::getSubTotalWithoutConditions();

// for a specific user
$subTotalWithoutConditions = Cart::session($userId)->getSubTotalWithoutConditions();

获取购物车的总额: Cart::getTotal()

/**
 * the new total in which conditions are already applied
 *
 * @return float
 */
$total = Cart::getTotal();

// for a specific user
$total = Cart::session($userId)->getTotal();

清除购物车: Cart::clear()

/**
* clear cart
*
* @return void
*/
Cart::clear();
Cart::session($userId)->clear();

条件

Laravel 购物车支持购物车条件。条件在(优惠券、折扣、销售、按商品销售和折扣等)方面非常有用。下面仔细查看如何使用条件。

条件可以添加到

1.) 整个购物车价值基础

2.) 每件商品基础

首先,让我们在购物车基础上添加一个条件

还有几种方法可以向购物车添加条件:注意

当在购物车基础上添加条件时,'target' 应具有值为 'subtotal' 或 'total'。如果目标是 "subtotal",则此条件将应用于小计。如果目标是 "total",则此条件将应用于总额。操作顺序在计算时也会根据您添加条件的顺序而变化。

此外,在添加条件时,'value' 字段将是计算的基础。您可以通过在 CartCondition 中添加 'order' 参数来更改此顺序。

// add single condition on a cart bases
$condition = new \Darryldecode\Cart\CartCondition(array(
    'name' => 'VAT 12.5%',
    'type' => 'tax',
    'target' => 'subtotal', // this condition will be applied to cart's subtotal when getSubTotal() is called.
    'value' => '12.5%',
    'attributes' => array( // attributes field is optional
    	'description' => 'Value added tax',
    	'more_data' => 'more data here'
    )
));

Cart::condition($condition);
Cart::session($userId)->condition($condition); // for a speicifc user's cart

// or add multiple conditions from different condition instances
$condition1 = new \Darryldecode\Cart\CartCondition(array(
    'name' => 'VAT 12.5%',
    'type' => 'tax',
    'target' => 'subtotal', // this condition will be applied to cart's subtotal when getSubTotal() is called.
    'value' => '12.5%',
    'order' => 2
));
$condition2 = new \Darryldecode\Cart\CartCondition(array(
    'name' => 'Express Shipping $15',
    'type' => 'shipping',
    'target' => 'subtotal', // this condition will be applied to cart's subtotal when getSubTotal() is called.
    'value' => '+15',
    'order' => 1
));
Cart::condition($condition1);
Cart::condition($condition2);

// Note that after adding conditions that are targeted to be applied on subtotal, the result on getTotal()
// will also be affected as getTotal() depends in getSubTotal() which is the subtotal.

// add condition to only apply on totals, not in subtotal
$condition = new \Darryldecode\Cart\CartCondition(array(
    'name' => 'Express Shipping $15',
    'type' => 'shipping',
    'target' => 'total', // this condition will be applied to cart's total when getTotal() is called.
    'value' => '+15',
    'order' => 1 // the order of calculation of cart base conditions. The bigger the later to be applied.
));
Cart::condition($condition);

// The property 'order' lets you control the sequence of conditions when calculated. Also it lets you add different conditions through for example a shopping process with multiple
// pages and still be able to set an order to apply the conditions. If no order is defined defaults to 0

// NOTE!! On current version, 'order' parameter is only applicable for conditions for cart bases. It does not support on per item conditions.

// or add multiple conditions as array
Cart::condition([$condition1, $condition2]);

// To get all applied conditions on a cart, use below:
$cartConditions = Cart::getConditions();
foreach($cartConditions as $condition)
{
    $condition->getTarget(); // the target of which the condition was applied
    $condition->getName(); // the name of the condition
    $condition->getType(); // the type
    $condition->getValue(); // the value of the condition
    $condition->getOrder(); // the order of the condition
    $condition->getAttributes(); // the attributes of the condition, returns an empty [] if no attributes added
}

// You can also get a condition that has been applied on the cart by using its name, use below:
$condition = Cart::getCondition('VAT 12.5%');
$condition->getTarget(); // the target of which the condition was applied
$condition->getName(); // the name of the condition
$condition->getType(); // the type
$condition->getValue(); // the value of the condition
$condition->getAttributes(); // the attributes of the condition, returns an empty [] if no attributes added

// You can get the conditions calculated value by providing the subtotal, see below:
$subTotal = Cart::getSubTotal();
$condition = Cart::getCondition('VAT 12.5%');
$conditionCalculatedValue = $condition->getCalculatedValue($subTotal);

注意:所有基于购物车的条件应该在调用 Cart::getTotal() 之前添加到购物车条件中,如果有针对小计应用的条件,也应该在调用 Cart::getSubTotal() 之前添加到购物车条件中。

$cartTotal = Cart::getSubTotal(); // the subtotal with the conditions targeted to "subtotal" applied
$cartTotal = Cart::getTotal(); // the total with the conditions targeted to "total" applied
$cartTotal = Cart::session($userId)->getSubTotal(); // for a specific user's cart
$cartTotal = Cart::session($userId)->getTotal(); // for a specific user's cart

接下来是针对每个商品的条件的设置。

如果您有特定的优惠券需要应用在单个商品上而不是整个购物车价值上,这非常有用。

注意:在添加基于每个商品的条件下,不需要或不允许使用'target'参数,与添加基于购物车或基于条件的不同。

现在让我们添加一个针对商品的条目。

// lets create first our condition instance
$saleCondition = new \Darryldecode\Cart\CartCondition(array(
            'name' => 'SALE 5%',
            'type' => 'tax',
            'value' => '-5%',
        ));

// now the product to be added on cart
$product = array(
            'id' => 456,
            'name' => 'Sample Item 1',
            'price' => 100,
            'quantity' => 1,
            'attributes' => array(),
            'conditions' => $saleCondition
        );

// finally add the product on the cart
Cart::add($product);

// you may also add multiple condition on an item
$itemCondition1 = new \Darryldecode\Cart\CartCondition(array(
    'name' => 'SALE 5%',
    'type' => 'sale',
    'value' => '-5%',
));
$itemCondition2 = new CartCondition(array(
    'name' => 'Item Gift Pack 25.00',
    'type' => 'promo',
    'value' => '-25',
));
$itemCondition3 = new \Darryldecode\Cart\CartCondition(array(
    'name' => 'MISC',
    'type' => 'misc',
    'value' => '+10',
));

$item = array(
          'id' => 456,
          'name' => 'Sample Item 1',
          'price' => 100,
          'quantity' => 1,
          'attributes' => array(),
          'conditions' => [$itemCondition1, $itemCondition2, $itemCondition3]
      );

Cart::add($item);

注意:所有基于购物车商品的条目应该在使用 Cart::getSubTotal() 之前添加。

最后,您可以调用 Cart::getSubTotal() 来获取具有每个商品应用条件的购物车小计。

// the subtotal will be calculated based on the conditions added that has target => "subtotal"
// and also conditions that are added on per item
$cartSubTotal = Cart::getSubTotal();

向购物车中现有的商品添加条件: Cart::addItemCondition($productId, $itemCondition)

向购物车中现有的商品添加条件同样简单。

这在结账过程中添加新的商品条件(如优惠券和促销代码)时非常有用。让我们看看如何操作的示例。

$productID = 456;
$coupon101 = new CartCondition(array(
            'name' => 'COUPON 101',
            'type' => 'coupon',
            'value' => '-5%',
        ));

Cart::addItemCondition($productID, $coupon101);

清除购物车条件: Cart::clearCartConditions()

/**
* clears all conditions on a cart,
* this does not remove conditions that has been added specifically to an item/product.
* If you wish to remove a specific condition to a product, you may use the method: removeItemCondition($itemId,$conditionName)
*
* @return void
*/
Cart::clearCartConditions()

删除特定的购物车条件: Cart::removeCartCondition($conditionName)

/**
* removes a condition on a cart by condition name,
* this can only remove conditions that are added on cart bases not conditions that are added on an item/product.
* If you wish to remove a condition that has been added for a specific item/product, you may
* use the removeItemCondition(itemId, conditionName) method instead.
*
* @param $conditionName
* @return void
*/
$conditionName = 'Summer Sale 5%';

Cart::removeCartCondition($conditionName)

删除特定的商品条件: Cart::removeItemCondition($itemId, $conditionName)

/**
* remove a condition that has been applied on an item that is already on the cart
*
* @param $itemId
* @param $conditionName
* @return bool
*/
Cart::removeItemCondition($itemId, $conditionName)

清除所有商品条件: Cart::clearItemConditions($itemId)

/**
* remove all conditions that has been applied on an item that is already on the cart
*
* @param $itemId
* @return bool
*/
Cart::clearItemConditions($itemId)

按类型获取条件: Cart::getConditionsByType($type)

/**
* Get all the condition filtered by Type
* Please Note that this will only return condition added on cart bases, not those conditions added
* specifically on an per item bases
*
* @param $type
* @return CartConditionCollection
*/
public function getConditionsByType($type)

按类型删除条件: Cart::removeConditionsByType($type)

/**
* Remove all the condition with the $type specified
* Please Note that this will only remove condition added on cart bases, not those conditions added
* specifically on an per item bases
*
* @param $type
* @return $this
*/
public function removeConditionsByType($type)

商品

Cart::getContent() 方法返回一个商品集合。

要获取商品的 ID,请使用属性 $item->id

要获取商品名称,请使用属性 $item->name

要获取商品数量,请使用属性 $item->quantity

要获取商品的属性,请使用属性 $item->attributes

要获取未应用条件的单个商品价格,请使用属性 $item->price

要获取未应用条件的单个商品小计,请使用方法 $item->getPriceSum()

/**
* get the sum of price
*
* @return mixed|null
*/
public function getPriceSum()

要获取未应用条件的单个商品价格,请使用方法

$item->getPriceWithConditions().

/**
* get the single price in which conditions are already applied
*
* @return mixed|null
*/
public function getPriceWithConditions()

要获取应用了条件的单个商品小计,请使用方法

$item->getPriceSumWithConditions()

/**
* get the sum of price in which conditions are already applied
*
* @return mixed|null
*/
public function getPriceSumWithConditions()

注意:当获取应用了条件的价格时,只有分配给当前商品的条目将被计算。购物车条件不会应用于价格。

关联模型

可以将购物车商品与模型关联。假设您在应用程序中有一个 Product 模型。使用 associate() 方法,您可以告诉购物车购物车中的某个商品与 Product 模型相关联。

这样,您就可以使用属性 $item->model 访问您的模型。

以下是一个示例

// add the item to the cart.
$cartItem = Cart::add(455, 'Sample Item', 100.99, 2, array())->associate('Product');

// array format
Cart::add(array(
    'id' => 456,
    'name' => 'Sample Item',
    'price' => 67.99,
    'quantity' => 4,
    'attributes' => array(),
    'associatedModel' => 'Product'
));

// add multiple items at one time
Cart::add(array(
  array(
      'id' => 456,
      'name' => 'Sample Item 1',
      'price' => 67.99,
      'quantity' => 4,
      'attributes' => array(),
      'associatedModel' => 'Product'
  ),
  array(
      'id' => 568,
      'name' => 'Sample Item 2',
      'price' => 69.25,
      'quantity' => 4,
      'attributes' => array(
        'size' => 'L',
        'color' => 'blue'
      ),
      'associatedModel' => 'Product'
  ),
));

// Now, when iterating over the content of the cart, you can access the model.
foreach(Cart::getContent() as $row) {
	echo 'You have ' . $row->qty . ' items of ' . $row->model->name . ' with description: "' . $row->model->description . '" in your cart.';
}

注意:这仅在添加商品到购物车时有效。

实例

您可能还希望在同一页面上有多个购物车实例而不发生冲突。为此,

创建一个新的服务提供者,然后在 register() 方法中,您可以这样做

$this->app['wishlist'] = $this->app->share(function($app)
		{
			$storage = $app['session']; // laravel session storage
			$events = $app['events']; // laravel event handler
			$instanceName = 'wishlist'; // your cart instance name
			$session_key = 'AsASDMCks0ks1'; // your unique session key to hold cart items

			return new Cart(
				$storage,
				$events,
				$instanceName,
				$session_key
			);
		});

// for 5.4 or newer
use Darryldecode\Cart\Cart;
use Illuminate\Support\ServiceProvider;

class WishListProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('wishlist', function($app)
        {
            $storage = $app['session'];
            $events = $app['events'];
            $instanceName = 'cart_2';
            $session_key = '88uuiioo99888';
            return new Cart(
                $storage,
                $events,
                $instanceName,
                $session_key,
                config('shopping_cart')
            );
        });
    }
}

如果您在使用多个购物车实例时遇到问题,请参阅此演示仓库中的代码:[DEMO](https://github.com/darryldecode/laravelshoppingcart-demo)

异常

目前只有两个异常。

事件

购物车当前有 9 个事件可供监听和挂钩。

注意:对于不同的购物车实例,处理事件很简单。例如,如果您创建了另一个购物车实例,并将其实例名称设置为 "wishlist"。事件将类似于:{$instanceName}.created($cart)

所以对于您的 wishlists 购物车实例,事件将类似于这样

  • wishlist.created($cart)
  • wishlist.adding($items, $cart)
  • wishlist.added($items, $cart) 以及其他事件。

格式化响应

现在您可以格式化所有响应。您可以从包中发布配置文件或使用环境变量来设置配置。您有的选项是

  • 格式化数字或env('SHOPPING_FORMAT_VALUES', false) => 启用或禁用此功能。默认为false。
  • 小数位数或env('SHOPPING_DECIMALS', 0) => 您想显示的小数位数。默认为0。
  • 小数点或env('SHOPPING_DEC_POINT', '.') => 小数点类型。默认为一个'.'。
  • 千位分隔符或env('SHOPPING_THOUSANDS_SEP', ',') => 价值的千位分隔符。默认为','。

示例

// add items to cart
Cart::add(array(
  array(
      'id' => 456,
      'name' => 'Sample Item 1',
      'price' => 67.99,
      'quantity' => 4,
      'attributes' => array()
  ),
  array(
      'id' => 568,
      'name' => 'Sample Item 2',
      'price' => 69.25,
      'quantity' => 4,
      'attributes' => array(
        'size' => 'L',
        'color' => 'blue'
      )
  ),
));

// then you can:
$items = Cart::getContent();

foreach($items as $item)
{
    $item->id; // the Id of the item
    $item->name; // the name
    $item->price; // the single price without conditions applied
    $item->getPriceSum(); // the subtotal without conditions applied
    $item->getPriceWithConditions(); // the single price with conditions applied
    $item->getPriceSumWithConditions(); // the subtotal with conditions applied
    $item->quantity; // the quantity
    $item->attributes; // the attributes

    // Note that attribute returns ItemAttributeCollection object that extends the native laravel collection
    // so you can do things like below:

    if( $item->attributes->has('size') )
    {
        // item has attribute size
    }
    else
    {
        // item has no attribute size
    }
}

// or
$items->each(function($item)
{
    $item->id; // the Id of the item
    $item->name; // the name
    $item->price; // the single price without conditions applied
    $item->getPriceSum(); // the subtotal without conditions applied
    $item->getPriceWithConditions(); // the single price with conditions applied
    $item->getPriceSumWithConditions(); // the subtotal with conditions applied
    $item->quantity; // the quantity
    $item->attributes; // the attributes

    if( $item->attributes->has('size') )
    {
        // item has attribute size
    }
    else
    {
        // item has no attribute size
    }
});

存储

使用不同的存储方式来存储购物车中的项目相当简单。注入到购物车实例的存储类只需要方法。

例如,我们需要一个心愿单,并希望将其键值对存储在数据库中而不是默认的会话。

为此,我们首先需要一个数据库表来存储我们的购物车数据。让我们通过执行php artisan make:migration create_cart_storage_table来创建它。

示例代码

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCartStorageTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('cart_storage', function (Blueprint $table) {
            $table->string('id')->index();
            $table->longText('cart_data');
            $table->timestamps();

            $table->primary('id');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('cart_storage');
    }
}

接下来,让我们创建一个Eloquent模型在这个表上,这样我们就可以轻松地处理数据。你可以根据自己的需求决定将这个模型存储在哪里。对于这个示例,我们假设将其存储在我们的App命名空间中。

代码

namespace App;

use Illuminate\Database\Eloquent\Model;


class DatabaseStorageModel extends Model
{
    protected $table = 'cart_storage';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'id', 'cart_data',
    ];

    public function setCartDataAttribute($value)
    {
        $this->attributes['cart_data'] = serialize($value);
    }

    public function getCartDataAttribute($value)
    {
        return unserialize($value);
    }
}

接下来,为你的存储创建一个新的类,以便将其注入到购物车实例中

例如:

class DBStorage {

    public function has($key)
    {
        return DatabaseStorageModel::find($key);
    }

    public function get($key)
    {
        if($this->has($key))
        {
            return new CartCollection(DatabaseStorageModel::find($key)->cart_data);
        }
        else
        {
            return [];
        }
    }

    public function put($key, $value)
    {
        if($row = DatabaseStorageModel::find($key))
        {
            // update
            $row->cart_data = $value;
            $row->save();
        }
        else
        {
            DatabaseStorageModel::create([
                'id' => $key,
                'cart_data' => $value
            ]);
        }
    }
}

例如,你也可以利用Laravel的缓存(redis、memcached、文件、dynamodb等),如下面的示例所示。示例还包括cookie持久性,这样购物车就可以持续30天。默认情况下,会话只持续20分钟。

namespace App\Cart;

use Carbon\Carbon;
use Cookie;
use Darryldecode\Cart\CartCollection;

class CacheStorage
{
    private $data = [];
    private $cart_id;

    public function __construct()
    {
        $this->cart_id = \Cookie::get('cart');
        if ($this->cart_id) {
            $this->data = \Cache::get('cart_' . $this->cart_id, []);
        } else {
            $this->cart_id = uniqid();
        }
    }

    public function has($key)
    {
        return isset($this->data[$key]);
    }

    public function get($key)
    {
        return new CartCollection($this->data[$key] ?? []);
    }

    public function put($key, $value)
    {
        $this->data[$key] = $value;
        \Cache::put('cart_' . $this->cart_id, $this->data, Carbon::now()->addDays(30));

        if (!Cookie::hasQueued('cart')) {
            Cookie::queue(
                Cookie::make('cart', $this->cart_id, 60 * 24 * 30)
            );
        }
    }
}

要使这成为购物车的默认存储,让我们更新购物车的配置文件。首先,让我们发布购物车配置文件,以便我们可以覆盖它。php artisan vendor:publish --provider="Darryldecode\Cart\CartServiceProvider" --tag="config"

运行该命令后,你的配置文件夹中应该会有一个新文件,名为shopping_cart.php

打开此文件,并更新存储使用。找到键名为'storage' => null,并将其更新为你的新创建的DBStorage类,在我们的例子中,'storage' => \App\DBStorage::class,

或者,如果你有多个购物车实例(例如心愿单),你可以通过将其注入到心愿单购物车的服务提供程序来将自定义数据库存储注入到购物车实例中,替换存储为使用你的自定义存储。见下文

use Darryldecode\Cart\Cart;
use Illuminate\Support\ServiceProvider;

class WishListProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('wishlist', function($app)
        {
            $storage = new DBStorage(); <-- Your new custom storage
            $events = $app['events'];
            $instanceName = 'cart_2';
            $session_key = '88uuiioo99888';
            return new Cart(
                $storage,
                $events,
                $instanceName,
                $session_key,
                config('shopping_cart')
            );
        });
    }
}

对于如何进行自定义数据库存储仍然感到困惑?或者,也许在进行多个购物车实例?查看演示仓库以查看代码以及如何根据您的需求进行扩展或将其作为指南和参考。请参阅以下链接

在此查看演示应用程序

或者

在此查看演示应用程序仓库

许可证

Laravel购物车是开源软件,许可协议为MIT许可证

免责声明

本软件按“原样”提供,并放弃所有明确或隐含的保证,包括但不限于适销性和针对特定目的的适用性隐含保证。在任何情况下,作者或任何贡献者均不对任何直接、间接、偶然、特殊、示范性或后果性损害(包括但不限于替代商品或服务的采购;使用、数据或利润的损失;或业务的中断)承担责任,即使被告知该软件存在此类损害的可能性。