13 KiB
13 KiB
Laravel Shop Package
A comprehensive headless e-commerce package for Laravel with stock management, Stripe integration, and product actions.
Features
- 🛍️ Product Management - Simple, variable, grouped, and external products
- 💰 Multi-Currency Support - Handle multiple currencies with ease
- 📦 Advanced Stock Management - Stock reservations, low stock alerts, and backorders
- 💳 Stripe Integration - Built-in Stripe product and price synchronization
- 🎯 Product Actions - Execute custom actions on product events (purchases, refunds)
- 🔗 Product Relations - Related products, upsells, and cross-sells
- 🌍 Translation Ready - Built-in meta translation support
- 📊 Stock Logging - Complete audit trail of stock changes
- 🎨 Headless Architecture - Perfect for API-first applications
- ⚡ Caching Support - Built-in cache management for better performance
- 🛒 Shopping Capabilities - Built-in trait for any purchaser model
- 🎭 Facade Support - Clean, expressive API through Shop and Cart facades
- 👤 Guest Cart Support - Session-based carts for unauthenticated users
Installation
composer require blax-software/laravel-shop
Publish the configuration:
php artisan vendor:publish --provider="Blax\Shop\ShopServiceProvider"
Run migrations:
php artisan migrate
Quick Start
Setup Your User Model
Add the HasShoppingCapabilities trait to any model that should be able to purchase products (typically your User model):
use Blax\Shop\Traits\HasShoppingCapabilities;
class User extends Authenticatable
{
use HasShoppingCapabilities;
// ...existing code...
}
Creating Your First Product
use Blax\Shop\Models\Product;
$product = Product::create([
'slug' => 'amazing-t-shirt',
'sku' => 'TSH-001',
'type' => 'simple',
'manage_stock' => true,
'status' => 'published',
]);
$product->prices()->create([
'currency' => 'USD',
'unit_amount' => 1999, // $19.99
'sale_unit_amount' => 1499, // $14.99
'is_default' => true,
]);
$product->adjustStock(StockType::INCREASE, 100); // Add 100 items to stock
$product->adjustStock(StockType::DECREASE, 90); // Remove 100 items from stock
$product->adjustStock(
StockType::CLAIMED,
10,
from: now(),
until: now()->addDay(),
note: 'Booked'
); // Claim/reserve 10 stocks
// Add translated name
$product->setLocalized('name', 'Amazing T-Shirt', 'en');
$product->setLocalized('description', 'A comfortable cotton t-shirt', 'en');
Working with Cart (Authenticated Users)
use Blax\Shop\Facades\Cart;
use Blax\Shop\Models\Product;
$product = Product::find($productId);
$user = auth()->user();
// Add to cart (via facade)
Cart::add($product, quantity: 2);
// Or via user trait
$cartItem = $user->addToCart($product, quantity: 1);
// Get cart totals
$total = Cart::total();
$itemCount = Cart::itemCount();
// Check if cart is empty
if (Cart::isEmpty()) {
// Cart is empty
}
// Remove from cart
Cart::remove($product);
// Clear entire cart
Cart::clear();
// Checkout cart
$completedPurchases = Cart::checkout();
Working with Guest Carts
use Blax\Shop\Facades\Cart;
// Create or retrieve guest cart (uses session ID automatically)
$guestCart = Cart::guest();
// Or with specific session ID
$guestCart = Cart::guest('custom-session-id');
// Add items to guest cart
$guestCart->addToCart($product, quantity: 1);
// Get guest cart totals
$total = Cart::total($guestCart);
$itemCount = Cart::itemCount($guestCart);
// Check if guest cart is empty
if (Cart::isEmpty($guestCart)) {
// Cart is empty
}
// Clear guest cart
Cart::clear($guestCart);
// Convert guest cart to user cart on login
$guestCart->convertToUserCart($user);
Purchasing Products Directly
use Blax\Shop\Models\Product;
$product = Product::find($productId);
$user = auth()->user();
// Simple purchase
$purchase = $user->purchase($product, quantity: 1);
// Purchase with options
$purchase = $user->purchase($product, quantity: 2, options: [
'price_id' => $priceId,
'charge_id' => $paymentIntent->id,
]);
// Check if user has purchased
if ($user->hasPurchased($product)) {
// Grant access
}
Using Shop Facade
use Blax\Shop\Facades\Shop;
// Get all products
$products = Shop::products()->get();
// Get published products only
$products = Shop::published()->get();
// Get products in stock
$products = Shop::inStock()->get();
// Get featured products
$featured = Shop::featured()->get();
// Search products
$results = Shop::search('t-shirt')->get();
// Check stock availability
if (Shop::checkStock($product, quantity: 5)) {
// Sufficient stock available
}
// Get available stock
$available = Shop::getAvailableStock($product);
// Check if product is on sale
if (Shop::isOnSale($product)) {
// Show sale badge
}
// Get configuration
$currency = Shop::currency(); // USD
$config = Shop::config('cart.expire_after_days', 30);
Documentation
Models
The package includes the following models:
- Product - Main product model with support for simple, variable, grouped, and external products
- ProductPrice - Multi-currency pricing with sale prices and subscription support
- ProductCategory - Hierarchical product categories
- ProductStock - Advanced stock management with reservations and logging
- ProductAttribute - Product attributes (size, color, material, etc.)
- ProductPurchase - Purchase records and history
- ProductAction - Custom actions triggered by product events
- ProductActionRun - Execution logs for product actions
- Cart - Shopping cart for authenticated users and guests
- CartItem - Individual items in a cart
- PaymentMethod - Saved payment methods
- PaymentProviderIdentity - Links users to payment providers (Stripe, etc.)
Traits
Available traits for your models:
- HasShoppingCapabilities - Complete shopping functionality (cart + purchases)
- HasCart - Cart management functionality only
- HasPaymentMethods - Payment method management
- HasStripeAccount - Stripe integration for users
- HasPrices - Price management (for Product model)
- HasStocks - Stock management (for Product model)
- HasCategories - Category relationships (for Product model)
- HasProductRelations - Related products, upsells, cross-sells
- HasChargingOptions - Payment processing capabilities
Facades
The package provides two facades for cleaner API access:
Shop Facade
use Blax\Shop\Facades\Shop;
Shop::products() // Get product query builder
Shop::product($id) // Find product by ID
Shop::categories() // Get categories query builder
Shop::inStock() // Get in-stock products
Shop::featured() // Get featured products
Shop::published() // Get published products
Shop::search($query) // Search products
Shop::checkStock($product, $qty) // Check stock availability
Shop::getAvailableStock($product) // Get available stock quantity
Shop::isOnSale($product) // Check if product is on sale
Shop::config($key, $default) // Get shop configuration
Shop::currency() // Get default currency
Cart Facade
use Blax\Shop\Facades\Cart;
Cart::current() // Get current user's cart
Cart::guest($sessionId) // Get/create guest cart
Cart::forUser($user) // Get cart for specific user
Cart::find($cartId) // Find cart by ID
Cart::add($product, $qty, $params) // Add item to cart
Cart::remove($product, $qty) // Remove item from cart
Cart::update($cartItem, $qty) // Update cart item quantity
Cart::clear($cart) // Clear cart items
Cart::checkout($cart) // Checkout cart
Cart::total($cart) // Get cart total
Cart::itemCount($cart) // Get item count
Cart::items($cart) // Get cart items
Cart::isEmpty($cart) // Check if cart is empty
Cart::isExpired($cart) // Check if cart is expired
Cart::isConverted($cart) // Check if cart was converted
Cart::unpaidAmount($cart) // Get unpaid amount
Cart::paidAmount($cart) // Get paid amount
Configuration
The config/shop.php file contains all configuration options:
return [
// Table names (customizable for multi-tenancy)
'tables' => [
'products' => 'products',
'product_categories' => 'product_categories',
'product_prices' => 'product_prices',
'product_stocks' => 'product_stocks',
'product_attributes' => 'product_attributes',
'product_purchases' => 'product_purchases',
'product_actions' => 'product_actions',
'product_action_runs' => 'product_action_runs',
'product_relations' => 'product_relations',
'carts' => 'carts',
'cart_items' => 'cart_items',
'cart_discounts' => 'cart_discounts',
'payment_methods' => 'payment_methods',
'payment_provider_identities' => 'payment_provider_identities',
],
// Model classes (allow overriding)
'models' => [
'product' => \Blax\Shop\Models\Product::class,
'product_price' => \Blax\Shop\Models\ProductPrice::class,
'product_category' => \Blax\Shop\Models\ProductCategory::class,
'product_stock' => \Blax\Shop\Models\ProductStock::class,
'product_attribute' => \Blax\Shop\Models\ProductAttribute::class,
'product_purchase' => \Blax\Shop\Models\ProductPurchase::class,
'cart' => \Blax\Shop\Models\Cart::class,
'cart_item' => \Blax\Shop\Models\CartItem::class,
'payment_provider_identity' => \Blax\Shop\Models\PaymentProviderIdentity::class,
'payment_method' => \Blax\Shop\Models\PaymentMethod::class,
],
// API Routes
'routes' => [
'enabled' => true,
'prefix' => 'api/shop',
'middleware' => ['api'],
'name_prefix' => 'shop.',
],
// Stock management
'stock' => [
'track_inventory' => true,
'allow_backorders' => false,
'low_stock_threshold' => 5,
'log_changes' => true,
'auto_release_expired' => true,
],
// Product actions
'actions' => [
'path' => app_path('Jobs/ProductAction'),
'namespace' => 'App\\Jobs\\ProductAction',
'auto_discover' => true,
],
// Stripe integration
'stripe' => [
'enabled' => env('SHOP_STRIPE_ENABLED', false),
'sync_prices' => true,
],
// Cache configuration
'cache' => [
'enabled' => env('SHOP_CACHE_ENABLED', true),
'ttl' => 3600,
'prefix' => 'shop:',
],
// Cart configuration
'cart' => [
'expire_after_days' => 30,
'auto_cleanup' => true,
'merge_on_login' => true,
],
// API response format
'api' => [
'include_meta' => true,
'wrap_response' => true,
'response_key' => 'data',
],
];
Commands
Add Example Products
Create example products for testing and demonstration purposes:
# Create 2 products of each type (default)
php artisan shop:add-example-products
# Create 5 products of each type
php artisan shop:add-example-products --count=5
# Clean existing example products first
php artisan shop:add-example-products --clean
This command creates:
- ✅ All 4 product types (simple, variable, grouped, external)
- ✅ Product categories
- ✅ Product attributes (material, size, color, etc.)
- ✅ Multiple pricing options (multi-currency, subscriptions)
- ✅ Example product actions (email notifications, stats updates)
- ✅ Variations for variable products
- ✅ Child products for grouped products
- ✅ Realistic data using Faker
Reinstall Shop Tables
# With confirmation
php artisan shop:reinstall
# Force without confirmation
php artisan shop:reinstall --force
⚠️ Warning: This will delete all shop data!
License
MIT License
Support
For issues and questions, please use the GitHub issue tracker.