From 8d6e1bcc2662d44fcbdb201e8205fc5c1d585ff5 Mon Sep 17 00:00:00 2001 From: Joel Male Date: Tue, 25 Feb 2025 13:49:09 +1000 Subject: [PATCH] wip: readme updates --- README.md | 162 +++++++++++++++++++++++------------------- docs/laravel-cart.png | Bin 0 -> 10195 bytes 2 files changed, 89 insertions(+), 73 deletions(-) create mode 100644 docs/laravel-cart.png diff --git a/README.md b/README.md index 743fddc..222964e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ + +[![Laravel Cart](./docs/laravel-cart.png)](https://joelmale.com) [![Latest Version on Packagist](https://img.shields.io/packagist/v/joelwmale/laravel-cart.svg?style=flat-square)](https://packagist.org/packages/joelwmale/laravel-cart) [![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/joelwmale/laravel-cart/tests.yml?branch=master&label=Tests)](https://github.com/joelwmale/laravel-cart/actions?query=workflow%3ATests+branch%3Amaster) [![Total Downloads](https://img.shields.io/packagist/dt/joelwmale/laravel-cart.svg?style=flat-square)](https://packagist.org/packages/joelwmale/laravel-cart) +[![GitHub last commit](https://img.shields.io/github/last-commit/joelwmale/laravel-cart)](#) [![License](https://poser.pugx.org/joelwmale/laravel-cart/license.svg)](https://packagist.org/packages/joelwmale/laravel-cart) +[![Free](https://img.shields.io/badge/free_for_non_commercial_use-brightgreen)](#-license) A Cart Implementation for Laravel. @@ -9,35 +13,58 @@ For Laravel 9.0 and below, please use version [1.0](https://github.com/joelwmale/laravel-cart/releases/tag/1.0.12) -## Quick Demo +## Table of Contents +- [Getting Started](#-getting-started) +- [Demo](#-deni) +- [Documentation](#-documentation) + - [Configuration](#configuration) + - [Basic Usage](#basic-usage) + - [Conditions](#conditions) + - [Items](#items) +- [Credits](#-credits) +- [License](#-license) -```php -// Add an item to the cart -\Cart::add(1, 'Product 1', 19.99, 2, ['size' => 'large']); - -// Get the cart contents -$cartContents = \Cart::getContent(); - -// Update item quantity by its id -\Cart::update(1, ['quantity' => 3]); - -// Remove an item from the cart by its id -\Cart::remove(1); - -// Get cart total -\$total = Cart::getTotal(); - -// Clear the entire cart -\Cart::clear(); -``` - -## Installing +## 🚀 Getting Started +### 🔥 Installing Install the package through [Composer](http://getcomposer.org/). `composer require "joelwmale/laravel-cart"` -## Configuration +## 🧑‍🍳 Demo + +```php +// Add an item to the cart +\Cart::add( + 1, // any unique id + 'Product 1', // product name + 19.99, // product price + 2, // quantity + ['size' => 'large'] // an array of extra attributes +); + +// get the entire cart +$cartContents = \Cart::getContent(); + +// update an item already in the cart +\Cart::update( + 1, // the same unique id that was used to add the item + ['quantity' => 3] // the quantity to update +); + +// remove the item by its id +\Cart::remove(1); + +// get the total of the cart +\$total = Cart::getTotal(); + +// clear it all when you've finished (like when you've stored the order) +\Cart::clear(); +``` + +## 📚 Documentation + +### ⚙️ Configuration You can publish the configuration file to customize various options. @@ -45,7 +72,7 @@ ## Configuration php artisan vendor:publish --provider="Joelwmale\Cart\CartServiceProvider" --tag="config" ``` -### Formatting Numbers +#### Formatting Numbers The package by default does not use round to format numbers, and instead returns the number using floatval(). @@ -58,7 +85,7 @@ ### Formatting Numbers 'round_mode' => env('LARAVEL_CART_ROUND_MODE', 'down'), ``` -### Decimals +#### Decimals You can customize the number of decimals in the configuration file. @@ -68,7 +95,7 @@ ### Decimals 'decimals' => env('LARAVEL_CART_DECIMALS', 2), ``` -### Round Mode +#### Round Mode The package uses the `round` function to round the prices. You can customize the rounding mode in the configuration file. @@ -78,21 +105,8 @@ ### Round Mode 'round_mode' => env('LARAVEL_CART_ROUND_MODE', 'down'), ``` -## Usage -- [Basic Usage](#basic-usage) -- [Conditions](#conditions) -- [Items](#items) -- [Associating Models](#associating-models) -- [Instances](#instances) -- [Exceptions](#exceptions) -- [Events](#events) -- [Format Response](#format) -- [Examples](#examples) -- [Using Different Storage](#storage) -- [License](#license) - -## Usage +### Basic Usage The cart has a default sessionKey that holds the cart data and stores it in the session. @@ -111,7 +125,7 @@ ## Usage \Cart::session(User::first()->id)->add(1, 'Product 1', 19.99, 2, ['size' => 'large']); ``` -### Adding to the cart: **Cart::add()** +#### Adding to the cart: **Cart::add()** There are a few ways to add items to the cart. @@ -182,7 +196,7 @@ ### Adding to the cart: **Cart::add()** ); ``` -### Updating an item on a cart: **Cart::update()** +#### Updating an item on a cart: **Cart::update()** ```php Cart::update( @@ -221,14 +235,14 @@ ### Updating an item on a cart: **Cart::update()** ); ``` -### Removing an item on a cart: **Cart::remove()** +#### Removing an item on a cart: **Cart::remove()** ```php // Remove an item from the cart by its id Cart::remove(456); ``` -### Getting an item on a cart: **Cart::get()** +#### Getting an item on a cart: **Cart::get()** ```php // Get an item from the cart by its id @@ -238,7 +252,7 @@ ### Getting an item on a cart: **Cart::get()** $summedPrice = Cart::get($itemId)->getPriceSum(); ``` -### Getting the cart content: **Cart::getContent()** +#### Getting the cart content: **Cart::getContent()** ```php // Returns a collection of the cart's contents @@ -258,13 +272,13 @@ ### Getting the cart content: **Cart::getContent()** $cartTotalQuantity = Cart::getTotalQuantity(); ``` -### Cart subtotal: **Cart::getSubTotal()** +#### Cart subtotal: **Cart::getSubTotal()** ```php $subTotal = Cart::getSubTotal(); ``` -### Cart subtotal without conditions: **Cart::getSubTotalWithoutConditions()** +#### Cart subtotal without conditions: **Cart::getSubTotalWithoutConditions()** ```php $subTotalWithoutConditions = Cart::getSubTotalWithoutConditions(); @@ -276,19 +290,19 @@ ### Cart subtotal without conditions: **Cart::getSubTotalWithoutConditions()** $total = Cart::getTotal(); ``` -### Check if cart is empty: **Cart::isEmpty()** +#### Check if cart is empty: **Cart::isEmpty()** ```php Cart::isEmpty(); ``` -### Clearing the Cart: **Cart::clear()** +#### Clearing the Cart: **Cart::clear()** ```php Cart::clear(); ``` -## Conditions +### Conditions Conditions are very useful for adding things like discounts, taxes, shipping, etc. @@ -300,9 +314,9 @@ ## Conditions You can also provide an `order` to cart conditions which tells the cart in what order to apply the conditions. Item level conditions do not support the `order` parameter. -### Conditions on the cart +#### Conditions on the cart -#### Adding a condition to the cart: **Cart::condition()** +##### Adding a condition to the cart: **Cart::condition()** ```php // Add a single condition to the cart @@ -353,7 +367,7 @@ #### Adding a condition to the cart: **Cart::condition()** Cart::condition($shipping); ``` -#### Getting conditions on the cart: **Cart::getConditions()** +##### Getting conditions on the cart: **Cart::getConditions()** ```php // To get all applied conditions on a cart, use below: @@ -372,7 +386,7 @@ #### Getting conditions on the cart: **Cart::getConditions()** } ``` -#### Getting conditions on the cart as an array: **Cart::getConditions(array: true)** +##### Getting conditions on the cart as an array: **Cart::getConditions(array: true)** You can get all cart conditions in array format by passing "array: true". This is useful if you want to store the carts conditions on a Livewire component since by default we have collections inside collections for conditions which Livewire does not support. @@ -391,7 +405,7 @@ #### Getting conditions on the cart as an array: **Cart::getConditions(array: tr } ``` -#### Getting conditions by name: **Cart::getCondition($conditionName)** +##### Getting conditions by name: **Cart::getCondition($conditionName)** ```php $condition = Cart::getCondition('GST'); @@ -405,7 +419,7 @@ #### Getting conditions by name: **Cart::getCondition($conditionName)** $condition->getAttributes(); // the attributes of the condition, returns an empty [] if no attributes added ``` -#### Getting active conditions on the cart: **Cart::getConditions(active: true)** +##### Getting active conditions on the cart: **Cart::getConditions(active: true)** You can get only active conditions by passsing `active: true` to the `getConditions()` method. @@ -441,14 +455,14 @@ #### Getting active conditions on the cart: **Cart::getConditions(active: true)* // will return no conditions if the subtotal is $210 ``` -### Calculating condition value +##### Calculating condition value There are 2 ways to calculate the value of a condition: 1. Using the `getCalculatedValue` method on the condition instance 2. Using the `getCalculatedValueForCondition` method on the cart instance and passing the condition name -#### Using the `getCalculatedValue` method on the condition instance +##### Using the `getCalculatedValue` method on the condition instance ```php $subTotal = Cart::getSubTotal(); @@ -456,7 +470,7 @@ #### Using the `getCalculatedValue` method on the condition instance $conditionCalculatedValue = $condition->getCalculatedValue($subTotal); ``` -#### Using the `getCalculatedValueForCondition` method on the cart instance +##### Using the `getCalculatedValueForCondition` method on the cart instance This method automatically calculates the value of a condition by it's name based on the order of the conditions. @@ -489,7 +503,7 @@ #### Using the `getCalculatedValueForCondition` method on the cart instance Cart::getCalculatedValueForCondition('Gift Card'); // returns 0 as the coupon discount is applied first and brings the subtotal to 0 ``` -### Adding conditions that activate once a minimum value is met +##### Adding conditions that activate once a minimum value is met You can add a `minimum` amount required for a condition to activate. @@ -508,7 +522,7 @@ ### Adding conditions that activate once a minimum value is met Cart::condition($tenPercentOff) ``` -### Adding conditions that only activate up to a maximum value +##### Adding conditions that only activate up to a maximum value You can add a `maximum` amount required for a condition to activate. @@ -527,7 +541,7 @@ ### Adding conditions that only activate up to a maximum value Cart::condition($shipping) ``` -### Condition on items +#### Conditions on items Item conditions are useful if you have discounts to be applied specifically on an item and not on the whole cart value. @@ -588,7 +602,7 @@ ### Condition on items $cartSubTotal = Cart::getSubTotal(); ``` -#### Add a condition to an existing item on the cart: **Cart::addItemCondition($productId, $itemCondition)** +##### Add a condition to an existing item on the cart: **Cart::addItemCondition($productId, $itemCondition)** Adding Condition to an existing Item on the cart is simple as well. @@ -602,7 +616,7 @@ #### Add a condition to an existing item on the cart: **Cart::addItemCondition($ Cart::addItemCondition(456, $condition); ``` -### Clearing Cart Conditions: **Cart::clearCartConditions()** +#### Clearing Cart Conditions: **Cart::clearCartConditions()** This clears all cart level conditions, and does not affect item level conditions. @@ -616,25 +630,25 @@ ### Clearing Cart Conditions: **Cart::clearCartConditions()** Cart::clearAllConditions() ``` -### Remove a specific cart condtion: **Cart::removeCartCondition($conditionName)** +##### Remove a specific cart condtion: **Cart::removeCartCondition($conditionName)** ```php Cart::removeCartCondition('Summer Sale 5%') ``` -### Remove a specific item condition: **Cart::removeItemCondition($itemId, $conditionName)** +##### Remove a specific item condition: **Cart::removeItemCondition($itemId, $conditionName)** ```php Cart::removeItemCondition(456, 'SALE 5%') ``` -### Clear all item conditions: **Cart::clearItemConditions($itemId)** +##### Clear all item conditions: **Cart::clearItemConditions($itemId)** ```php Cart::clearItemConditions(456) ``` -### Get conditions by type: **Cart::getConditionsByType($type)** +#### Get conditions by type: **Cart::getConditionsByType($type)** This returns all conditions that has been added to the cart by the type specified. @@ -642,13 +656,13 @@ ### Get conditions by type: **Cart::getConditionsByType($type)** $tax = Cart::getConditionsByType('tax'); ``` -### Remove conditions by type: **Cart::removeConditionsByType($type)** +##### Remove conditions by type: **Cart::removeConditionsByType($type)** ```php Cart::removeConditionsByType('tax'); ``` -## Cart Items +### Cart Items The method **Cart::getContent()** returns a collection of items. @@ -670,8 +684,10 @@ ## Cart Items $item->getPriceSumWithConditions(); ``` -## Credits +## 🫡 Credits -Huge credits to the original maintainer of the package, located at [darryldecode/laravelshoppingcart](https://github.com/darryldecode/laravelshoppingcart) +This package was orignally created by [darryldecode](https://github.com/darryldecode) but has since seen almost no updates. I have decided to take the old package and transform it into a new package with new features and updates. -We have forked this package to update it to Laravel 11 and to add some features and support for newer PHP versions. \ No newline at end of file +## 📓 License + +The MIT License (MIT). Please see [License File](LICENSE.md) for more information. \ No newline at end of file diff --git a/docs/laravel-cart.png b/docs/laravel-cart.png new file mode 100644 index 0000000000000000000000000000000000000000..f8cac1fb394bda26720a800941129bfc9b5b826d GIT binary patch literal 10195 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 literal 0 HcmV?d00001