treehousetim/shopcart
Composer 安装命令:
composer require treehousetim/shopcart
包简介
A simple, zero-dependency, zero UI, Shopping Cart library.
README 文档
README
Shopping Cart Core Functionality PHP Library
Installing
composer require treehousetim/shopcart
Requirements
shopCart has no third-party package dependencies — installing it pulls in nothing but the library itself.
It does require PHP 7 or 8 and the bcmath extension,
which the library uses for exact decimal money math (amounts are handled as
strings, never floats). bcmath ships with PHP and is enabled by default on
most builds; if yours lacks it, install/enable ext-bcmath (e.g.
apt-get install php-bcmath, or the --enable-bcmath build flag).
Interfaces and Abstract Classes
In order to use the shopCart, you will need to instantiate both a treehousetim\shopCart\cart and a treehousetim\shopCart\catalog object.
The constructor for the cart requires a catalog object be passed.
In order for a catalog object to function, it requires a product loader be implemented that implements catalogLoaderInterface
use \treehousetim\shopCart\catalog; use \treehousetim\shopCart\cart; $catalog = ( new catalog() ) ->setProductLoader( new \application\cart\myProductLoader() ) ->populate(); $cart = new cart( $catalog ); $cart->setTotalTypeLoader( (new \application\cart\myCatalogTotalTypeLoader())) ->setFormatter( new \application\cart\myProductAmountFormatter() ) ->setStorageHandler( (new \treehousetim\shopCart\cartStorageSession() ) ) ->load();
catalogLoaderInterface
A catalog object is used to load products into the product catalog.
interface catalogLoaderInterface { public function hasProducts() : bool; public function nextProduct() : bool; public function getProduct() : product; }
cartStorageInterface
You can use a lot of different storage options for a cart. treehousetim\shopCart provides an implementation for session storage.
After creating your implementation of this interface, you must supply it to your cart using $cart->setStorageHandler( $storageHandler );
interface cartStorageInterface { public function loadCart( cart $cart ) : cartStorageInterface; public function emptyCart( cart $cart ) : cartStorageInterface; public function saveItems( array $items ) : cartStorageInterface; public function saveData( array $data ) : cartStorageInterface; // used to clean up after all storage is complete public function finalize( cart $cart ) : cartStorageInterface; }
catalogTotalTypeLoaderInterface
You must implement a class that conforms to this interface to support different types of product totals. Typical e-commerce shop carts will probably only need a single catalogTotalType for price, but there are other businesses that need totals of different product properties.
interface catalogTotalTypeLoaderInterface { public function nextType() : bool; public function getType() : catalogTotalType; public function resetType(); }
Here is a sample catalogTotalTypeLoaderInterface implementation for both price and some special case of "points"
<?php namespace application\libraries\cart; use treehousetim\shopCart\catalogTotalTypeLoaderInterface; use treehousetim\shopCart\catalogTotalType; class totalTypeLoader implements catalogTotalTypeLoaderInterface { protected $types; public function __construct() { $this->types[] = (new catalogTotalType( catalogTotalType::tPRODUCT_PRICE ) ); $this->types[] = (new catalogTotalType( catalogTotalType::tPRODUCT_FIELD ) ) ->setIdentifier( 1 ) ->setUnit( 'points' ) ->setLabel( 'Point' ) ->setProductField( 'productPoints' ); } //------------------------------------------------------------------------ public function nextType() : bool { next( $this->types ); if( key( $this->types ) === null ) { return false; } return true; } //------------------------------------------------------------------------ public function getType() : catalogTotalType { return current( $this->types ); } //------------------------------------------------------------------------ public function resetType() { reset( $this->types ); } }
Product Variations
A product can have variations along arbitrary attributes (color, size, …) using
productVariation. A variation wraps a parent product and falls back to the
parent for anything you don't override — name, description, image, category,
formatter, total type identifier, and price.
Every variation is itself a product: give it a unique id and add it to the
catalog alongside its parent. Because cart items are keyed by product id and
cartStorageSession re-resolves products from the catalog on load, this is all
that's needed for variations to survive a save/load round trip.
use treehousetim\shopCart\productVariation; $shirt = ( new myProduct() ) ->setId( 'shirt' ) ->setName( 'T-Shirt' ) ->setPrice( '20.00' ); $shirtXL = ( new productVariation( $shirt ) ) ->setAttribute( 'size', 'XL' ) ->setAttribute( 'color', 'blue' ) ->setId( 'shirt-xl-blue' ) ->setPrice( '24.50' ); // optional — omit to inherit the parent's price $catalog->addProduct( $shirt )->addProduct( $shirtXL ); $shirtXL->getAttribute( 'size' ); // 'XL' (unknown names throw // Exception::noSuchAttributeErrorCode) $shirtXL->getAttributes(); // ['size' => 'XL', 'color' => 'blue']
For carts with multiple total types, a variation can also override the per-unit
amount of any catalogTotalType::tPRODUCT_FIELD dimension with
setFieldAmount( $productField, $amount ). When no field amount is set for a
dimension, getAmountForCatalogTotalType() delegates to the parent product.
Serialized Variations
productVariationSerialized models variations where each unit is a distinct
physical item identified by a serial number. Rules enforced by the library:
- Quantity is always exactly 1 per serial.
cart::addProduct()with a quantity other than 1, orcart::updateItemQty()to anything other than 1, throwsException::serializedQtyErrorCode. - Adding the same serial twice throws
Exception::duplicateSerialErrorCode(an exception rather than a silent no-op, so the UI can tell the shopper the unit is already in the cart). The cart is left unchanged. - Id resolution: if you don't call
setId(), the id is derived asparentId . ':' . serialNumber, so each unit is unique in the catalog and the session round trip works unchanged. Add every serialized unit to the catalog like any other product.
Each serialized unit can carry its own amount for each total type — its own
price and its own per-unit amount for any tPRODUCT_FIELD dimension — so two
serials of the same product can total differently in every dimension:
use treehousetim\shopCart\productVariationSerialized; $unitA = ( new productVariationSerialized( $collectible ) ) ->setSerialNumber( 'SN-0001' ) ->setPrice( '102.75' ) ->setFieldAmount( 'points', '7.5' ); $unitB = ( new productVariationSerialized( $collectible ) ) ->setSerialNumber( 'SN-0002' ) ->setPrice( '99.10' ) ->setFieldAmount( 'points', '3.25' ); $catalog->addProduct( $unitA )->addProduct( $unitB ); $cart->addProduct( $unitA, 1 ); // qty must be exactly 1 $cart->addProduct( $unitB, 1 ); // cart::getAmountTotal()/getTotal() now sum the per-serial amounts
product::isSerialized() (false on every product except serialized variations)
lets storage handlers and UIs detect these items generically.
totalFormatterInterface
interface totalFormatterInterface { public function formatTotalType( string $value, catalogTotalType $type ); }
Testing
If you have cloned this repo, you can run the test suite. The library itself has no third-party dependencies; the tests use Pest, which is installed as a dev dependency by composer.
composer install./vendor/bin/pest
The suite lives under test/, with shared helpers in test/helpers.php
(loaded via composer's autoload-dev) and reusable fixtures in
test/fixture*.php. Note that Pest's runner requires PHP 8.2+; the library
itself still supports PHP ^7.0 at runtime.
To measure code coverage, run with a coverage driver enabled
(xdebug or pcov):
./vendor/bin/pest --coverage
The suite covers 100% of src/. If your PHP has no coverage driver, you
can measure it in a throwaway container:
docker run --rm -v "$PWD":/app -w /app php:8.3-cli sh -c '
apt-get update -qq && apt-get install -y -qq $PHPIZE_DEPS >/dev/null 2>&1
docker-php-ext-install bcmath >/dev/null 2>&1
pecl install pcov >/dev/null 2>&1 && docker-php-ext-enable pcov
php vendor/bin/pest --coverage'
treehousetim/shopcart 适用场景与选型建议
treehousetim/shopcart 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1.03k 次下载、GitHub Stars 达 1, 最近一次更新时间为 2020 年 04 月 30 日, 在 PHP 生态内属于活跃度较高的组件。
我们在过去多个企业项目中使用过 treehousetim/shopcart 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 treehousetim/shopcart 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
统计信息
- 总下载量: 1.03k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 11
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2020-04-30