Getting Started
Migration from Simple Commerce
This migration guide is still a work in progress - there's bound to be things missing. If you come across something which hasn't been covered here, please open an issue or a pull request.
Overview
Cargo is the natural evolution of Simple Commerce.
What started out as a hobby project for me to learn the internals of Statamic turned into the way to build e-commerce sites with Statamic.
Cargo takes everything you love about Simple Commerce, and makes it better in every possible way. Some of the big changes include....
- A complete re-working of carts & orders to ultimately make things faster and more reliable.
- A redesigned Control Panel UI, ensuring your admins can get what they need at a glance.
- A massive overhaul to discounting, allowing for automatic site-wide discounts, as well as traditional coupon-style discounts.
- Pre-built Checkout Page, allowing you to level up your customer's purchasing experience.
Licensing
Before deploying Cargo to production, you will need to obtain a new licence via the Statamic Marketplace.
Cargo now costs $199 for new licences, then $85 per year thereafter for support & updates, similar to Statamic Pro.
If you've purchased Simple Commerce within the last 12 months, you can migrate for free.
Otherwise, if you purchased Simple Commerce more than a year ago, you can migrate to Cargo for $85.
Either way, just email [email protected] with your order number, and I'll send you a coupon code to use at checkout.
Updating
To upgrade, uninstall Simple Commerce and install Cargo using composer:
composer remove duncanmcclean/simple-commerce
composer require duncanmcclean/cargo
Once composer has done its thing, run Cargo's install command to publish various stubs, select your products collection, and more:
php please cargo:install
Next, run the migrator script to copy over configuration options and migrate your data:
php please cargo:migrate
If you need to, you can safely re-run the cargo:migrate
command multiple times. You can also run each of the migrators independently:
php please cargo:migrate:configs
php please cargo:migrate:customers
php please cargo:migrate:discounts
php please cargo:migrate:taxes
php please cargo:migrate:orders
php please cargo:migrate:carts
php please cargo:migrate:products
Finally, please review this migration guide thoroughly. You will need to make code changes as part of this upgrade.
Consider making small, regular commits during the migration process. This makes it easier for you to revert any accidental changes or reference things in the future.
Products
Products haven't changed much - they're still entries in Statamic, like you're used to.
Migrating orders
Cargo will have attempted to automatically update your product entries when you ran the cargo:migrate
command.
If you need to, you can update just products using php please cargo:migrate:products
.
Product collections
It's now possible to configure multiple product collections. This may be handy if you want to split our digital products, like courses, from physical products, like merchandise.
You can specify additional collections in the cargo.php
config file:
// config/statamic/cargo.php
'products' => [
'collections' => ['courses', 'merch'],
],
Digital Products
To avoid cluttering the product publish form for stores selling only physical products, the Digital Product functionality is now opt-in:
// config/statamic/cargo.php
'digital_products' => true,
Like Simple Commerce, Cargo allows you to specify downloads for digital products, which will be available after an order is completed.
Cargo doesn't include the "licence keys" feature included in Simple Commerce. If you need this, we recommend building it yourself.
Cargo also doesn't track IP addresses & timestamps of downloads. If you need this, you can listen to the ProductDownloaded
event and update the line item accordingly:
// app/Providers/AppServiceProvider.php
Event::listen(ProductDownloaded::class, function ($event) {
$event->order->lineItems()->update($event->lineItem->id(), [
'download_history' => [
...$event->lineItem->get('download_history', []),
[
'timestamp' => now()->toIso8601String(),
'ip_address' => request()->ip(),
],
],
]);
$event->order->save();
});
Carts
In Simple Commerce, carts were basically just unpaid orders.
In Cargo, carts and orders are separate. A cart is created when a customer adds a product to their cart. An order is created when a customer checks out.
Migrating carts
Cargo will have attempted to automatically migrate existing carts when you ran the cargo:migrate
command.
If you need to, you can migrate just carts using php please cargo:migrate:carts
.
If you were previously storing orders in the database, Cargo will publish and run the relevant database migrations prior to migrating carts.
Abandoned carts
During the install process, Cargo will have added its purge-abandoned-carts
command to your app's routes/console.php
file.
If you were previously scheduling Simple Commerce's sc:purge-cart-orders
command, either in routes/console.php
or app/Console/Kernel.php
, you can remove it.
Orders
Orders are now stored within their own "stache store", making them independent from collections/entries.
This change was made for a variety reasons, with the main one being that it gives Cargo more control around how everything works, than piggybacking on collections.
Migrating orders
Cargo will have attempted to automatically migrate existing orders when you ran the cargo:migrate
command.
If you need to, you can migrate just orders using php please cargo:migrate:orders
.
If you were previously storing orders in the database, Cargo will publish and run the relevant database migrations prior to migrating orders.
Blueprint
Since orders are no longer stored in collections, Cargo provides its own "Order" blueprint, which can be edited via the Blueprints page in the Control Panel:
During the migration process, Cargo will have attempted to copy across any custom fields you added to the order collection's blueprint.
Status Log
The "Status Log" feature present in Simple Commerce doesn't exist in Cargo. Cargo simply displays the current status of orders.
If you need to occasionally reference the history of order statuses, you may wish to take advantage of Statamic's Git Automation if you're storing orders in flat files, or use a package like spatie/laravel-activitylog
if you're using a database.
Customers
By default, Simple Commerce stored information about your customers in a customers collection or customers
database table.
Upon reflecting, this setup didn't really make sense and kinda became a pain if you wanted customers to login to your site in the future.
In Cargo, there are two types of customers:
- Users
- These are plain old Statamic users.
- When a customer is logged in, the logged-in user will be automatically associated with the cart.
- This makes it easy to manage your customers in the Control Panel and built user account functionality, if needed.
- Guest customers
- Guest customers are saved on individual orders, useful for stores without user accounts.
- You need to provide
customer[name]
andcustomer[email]
inputs during checkout for a guest customer to be created
Migrating customers
Cargo will have attempted to automatically migrate existing customers when you ran the cargo:migrate
command.
If you need to, you can migrate just customers using php please cargo:migrate:customers
.
You should still run the migration command if you were previously storing customers as users, as it'll remove the
orders
key from user data (it is now a computed field).
Discounting
Cargo builds on top of the coupons feature in Simple Commerce, allowing you to create site-wide discounts which are automatically applied to eligible carts.
If you only want a discount to be redeemable using a coupon code (like how it worked in Simple Commerce), you can specify a "Discount code" on the discount.
Behaviour changes
There are a few notable behaviour changes when compared with Simple Commerce's coupons feature...
- Discounts can no longer be limited by email domain, only be linking existing customers.
- Discounts are now calculated on individual line items, rather than the cart as a whole.
- It's now possible for multiple discounts to be applied at once.
- Although, there can only be one discount code applied at once.
- Simple Commerce prevented customers from applying coupon codes which weren't eligible for items in the cart.
- This isn't the same in Cargo. Customers can apply discount codes, even when none of the eligible products are in the cart.
- Obviously, in this case, no discount will actually be applied.
- This isn't the same in Cargo. Customers can apply discount codes, even when none of the eligible products are in the cart.
Migrating discounts
Cargo will have attempted to automatically migrate existing discounts when you ran the cargo:migrate
command.
If you need to, you can migrate just discounts using php please cargo:migrate:discounts
.
Taxes
The whole tax situation in Simple Commerce was pretty confusing... there were two tax engines, you had to go through multiple screens to wire stuff up. Not an ideal UX.
Taxation has been drastically improved in Cargo. There's now only "one" tax engine - it has two concepts:
- Tax Classes are assigned to products, representing the "rate" of tax which should be applied
- Tax Zones represent the physical area where certain tax rules apply.
- This is where you set rates for each of the configured tax classes.
Configuration
By default, prices are inclusive of tax. If you would rather them be exclusive of taxes instead, you can disable the behaviour in the cargo.php
config file:
// config/statamic/cargo.php
'taxes' => [
// Enable this when product prices are entered inclusive of tax.
// When calculating taxes, the tax will be deducted from the product price, then added back on at the end.
'price_includes_tax' => true,
],
Migrating taxes
Cargo will have attempted to automatically migrate your tax configuration when you ran the cargo:migrate
command.
If you need to, you can migrate just taxes using php please cargo:migrate:taxes
.
Frontend
Antlers
Cargo has renamed and removed a lot of tags from Simple Commerce. For ease of reference, a table has been provided below with the old tag, and the new/alternative tag in Cargo.
You should use the "find & replace" feature in your code editor to well... find & replace references to the old tags in your templates.
Old | New |
---|---|
{{ sc:cart }} |
{{ cart }} |
{{ sc:cart:* }} |
{{ cart:* }} |
{{ sc:cart:has }} |
{{ cart:exists }} |
{{ sc:cart:items }} |
{{ cart:line_items }} |
{{ sc:cart:count }} |
{{ {cart:line_items} | count }} |
{{ sc:cart:quantity_total }} |
{{ {cart:line_items} | sum('quantity') }} |
{{ sc:cart:total }} |
{{ cart:grand_total }} |
{{ sc:cart:free }} |
{{ cart:is_free }} |
{{ sc:cart:grand_total }} |
{{ cart:grand_total }} |
{{ sc:cart:raw_grand_total }} |
{{ cart:grand_total | raw }} |
{{ sc:cart:items_total }} |
{{ cart:sub_total }} |
{{ sc:cart:raw_items_total }} |
{{ cart:sub_total | raw }} |
{{ sc:cart:items_total_with_tax }} |
{{ {cart:sub_total} + {cart:line_items | sum('tax_total')} }} |
{{ sc:cart:shipping_total }} |
{{ cart:shipping_total }} |
{{ sc:cart:raw_shipping_total }} |
{{ cart:shipping_total | raw }} |
{{ sc:cart:shipping_total_with_tax }} |
{{ {cart:shipping_total} + {cart:shipping_tax_total} }} |
{{ sc:cart:tax_total }} |
{{ cart:tax_total }} |
{{ sc:cart:raw_tax_total }} |
{{ cart:tax_total | raw }} |
{{ sc:cart:tax_total_split }} |
{{ cart:tax_breakdown }} You can output rate , description , zone and amount . |
{{ sc:cart:raw_tax_total_split }} |
{{ cart:tax_breakdown | raw }} |
{{ sc:cart:coupon_total }} |
{{ cart:discount_total }} |
{{ sc:cart:raw_coupon_total }} |
{{ cart:discount_total | raw }} |
{{ sc:cart:addItem }} / {{ sc:cart:add_item }} |
{{ cart:add }} |
{{ sc:cart:updateItem }} / {{ sc:cart:update_item }} |
{{ cart:update_line_item }} |
{{ sc:cart:removeItem }} / {{ sc:cart:remove_item }} |
{{ cart:remove }} |
{{ sc:cart:update }} |
{{ cart:update }} |
{{ sc:cart:empty }} |
{{ cart:delete }} |
{{ sc:cart:alreadyExists }} / {{ sc:cart:already_exists }} |
{{ cart:added }} |
{{ sc:checkout }} |
Removed. See the Checkout section below. |
{{ sc:checkout:* }} |
Removed. See the Checkout section below. |
{{ sc:coupon }} |
Removed |
{{ sc:coupon:has }} |
{{ if {cart:discount_code} }} |
{{ sc:coupon:redeem }} |
antlers<br>{{ cart:update }}<br> <input name="discount_code"><br>{{ /cart:update }}<br> |
{{ sc:coupon:remove }} |
antlers<br>{{ cart:update }}<br> <input name="discount_code"><br>{{ /cart:update }}<br> To remove a discount code, an empty discount_code input should be probided. |
{{ sc:coupon:* }} |
Removed |
{{ sc:customer:* }} |
{{ cart:customer }} |
{{ sc:customer:update }} |
antlers<br>{{ cart:update }}<br> <input name="customer[name]"><br> <input name="customer[email]"><br>{{ /cart:update }}<br> You can alternatively use Statamic's profile_form tag. |
{{ sc:customer:orders }} |
{{ orders :customer:is="cart:customer:id" }} |
{{ sc:customer:order }} |
{{ orders :customer:is="cart:customer:id" :id:is="get:order_id" }} |
{{ sc:gateway }} |
{{ payment_gateways }} |
{{ sc:gateway:count }} |
{{ payment_gateways | count }} |
{{ sc:gateway:* }} |
Removed. |
{{ sc:shipping:methods }} |
{{ shipping_methods }} |
{{ sc:countries }} |
{{ dictionary:countries }} Uses Statamic's built-in country dictionary. |
{{ sc:currencies }} |
Removed. |
{{ sc:regions }} |
{{ states }} |
{{ sc:errors }} |
{{ get_errors:all }} The get_errors tag is built into Statamic. |
{{ sc:has_errors }} / {{ sc:hasErrors }} |
{{ {get_errors:all | count} > 0 }} The get_errors tag is built into Statamic. |
In addition to changes of tag names, some variables have been renamed as well. A non-exclusive list is provided below:
Old | New |
---|---|
items |
line_items |
items_total |
sub_total |
coupon_total |
discount_total |
gateway |
payment_gateway |
free |
is_free |
total_including_tax |
Removed. |
The
{{ dump }}
tag is an easy way of debugging data inside the current view context (eg. seeing which variables are defined at the current point in time).
The currency
modifier has been removed in Cargo.
Blade
If you prefer to use Laravel Blade, a lot of the changes mentioned in the Antlers section will still apply. Please review it and make any necessary changes.
JSON API
The JSON API has changed quite a bit between Simple Commerce and Cargo, including the URLs of endpoints and the structure of responses.
You can find a mapping of API endpoints below:
Old | New |
---|---|
GET /!/simple-commerce/cart |
GET /!/cargo/cart |
POST /!/simple-commerce/cart |
POST /!/cargo/cart |
DELETE /!/simple-commerce/cart |
DELETE /!/cargo/cart |
POST /!/simple-commerce/cart-items |
POST /!/cargo/cart/line-items |
POST /!/simple-commerce/cart-items/{cartItem} |
POST /!/cargo/cart/line-items/{lineItem} |
DELETE /!/simple-commerce/cart-items/{cartItem} |
DELETE /!/cargo/cart/line-items/{lineItem} |
GET /!/simple-commerce/customer/{customer} |
Removed. |
POST /!/simple-commerce/customer/{customer} |
Removed, in favour of updating the customer via the POST /!/cargo/cart endpoint.Alternatively, you could make an AJAX request to the {{ user:profile_form }} endpoint. |
POST /!/simple-commerce/checkout |
Removed. See the Checkout section below. |
POST /!/simple-commerce/coupon |
Removed, in favour of updating the discount code via the POST /!/cargo/cart endpoint. |
DELETE /!/simple-commerce/coupon |
Removed, in favour of removing the discount code via the POST /!/cargo/cart endpoint. |
For more information about the JSON API, please consult the JSON API page.
Checkout
To improve performance and reliability, the checkout process has been completely re-worked in Cargo. As a result, you will need to makes changes to your checkout templates.
If you're not too precious about your checkout page, you might be better off adopting Cargo's new pre-built checkout flow instead.
It'll save you a lot of time and effort. It also reduces friction for customers, handling everything on a single page.
Cargo removes the {{ checkout }}
tag, which was used for collecting the customer's payment details.
In its place, each payment gateway now has a dedicated checkout URL, which can either be passed as a return/callback URL to the gateway, or submitted using a <form>
.
The checkout URL will handle validation and the creation of the order.
You can use the {{ payment_gateways }}
tag to loop through the cart's available payment gateways:
{{ payment_gateways }}
<details name="payment_gateway" {{ if first }} open {{ /if }}>
<summary>{{ name }}</summary>
<div>
{{ partial src="checkout/payment-forms/{handle}" }}
</div>
</details>
{{ /payment_gateways }}
Inside the loop, you have access to the following variables:
name
handle
checkout_url
- Anything returned by the payment gateway's
setup
method.
Every payment gateway should provide a "payment form" template in its documentation.
In the above example, each payment form lives in its own partial, so you can create one and copy the provided code into there.
When the cart total is $0, you should instead display a generic checkout URL, which'll handle validation and creating the order:
{{ if {cart:is_free} }}
<form action="{{ route:statamic.cargo.cart.checkout }}">
<p>{{ 'No payment required. Continue to checkout.' | trans }}</p>
<button>Checkout</button>
</form>
{{ /if }}
For more information, and examples on building custom checkout flows, please see the Checkout page.
Payments
After migrating to Cargo, you'll need to re-configure your site's payment gateways in the cargo.php
config file.
Dummy
Configuration
Cargo will have attempted to automatically migrate the payment.gateways
array in the cargo.php
config file. However, if it wasn't able to, you can update it yourself:
// config/statamic/cargo.php
'payments' => [
'gateways' => [
+ 'dummy' => [], ],
],
Payment form
If you're adopting Cargo's pre-built checkout flow, you don't need to do this step.
You will need to update the payment form for the Dummy payment gateway in your templates. You can find the latest version on the Payment Gateways page.
Stripe
Configuration
Cargo will have attempted to automatically migrate the payment.gateways
array in the cargo.php
config file. However, if it wasn't able to, you can update it yourself:
// config/statamic/cargo.php
'payments' => [
'gateways' => [
+ 'stripe' => [ + 'key' => env('STRIPE_KEY'), + 'secret' => env('STRIPE_SECRET'), + 'webhook_secret' => env('STRIPE_WEBHOOK_SECRET'), + ], ],
],
Payment form
If you're adopting Cargo's pre-built checkout flow, you don't need to do this step.
You will need to update the payment form for the Stripe payment gateway in your templates. You can find the latest version on the Payment Gateways page.
Webhook
When deploying your changes, you will need to update your webhook URL in the Stripe Dashboard.
Previously, the webhook URL was /!/simple-commerce/gateways/stripe/webhook
. It is now /!/cargo/payments/stripe/webhook
.
If you don't already have a Stripe webhook configured, you will need to create one. It should listen for all charge and payment intent events.
Whilst not strictly required, we highly recommend configuring a "webhook secret" to prevent malicious requests to the webhook.
You can find the webhook secret on the "Webhooks" page in the Stripe dashboard.
STRIPE_WEBHOOK_SECRET=whsec_...
Behaviour changes
The authorization and capture steps have been separated to account for incomplete/cancelled orders.
- Authorization happens when the customer submits the checkout form.
- Capturing (actually taking the payment) happens when the webhook is received.
Mollie
Configuration
Cargo will have attempted to automatically migrate the payment.gateways
array in the cargo.php
config file. However, if it wasn't able to, you can update it yourself:
// config/statamic/cargo.php
'payments' => [
'gateways' => [
+ 'mollie' => [ + 'api_key' => env('MOLLIE_KEY'), + 'profile_id' => env('MOLLIE_PROFILE_ID'), + ], ],
],
Payment form
If you're adopting Cargo's pre-built checkout flow, you don't need to do this step.
You will need to update the payment form for the Mollie payment gateway in your templates. You can find the latest version on the Payment Gateways page.
PayPal
Cargo doesn't have a built-in PayPal payment gateway, but you can use it via another payment gateway like Stripe or Mollie.
PayPal deprecated their official PHP SDK in 2023, and it's not widely used enough to warrant building an updated version for Cargo. If someone builds a PayPal payment gateway for Cargo, and releases it as an addon, I'm happy to link to it here.
Custom payment gateways
You should be able to re-use most of your existing code. It'll just need to be adjusted to work with Cargo's APIs.
API Changes
Payment Gateways should extend Cargo's abstract PaymentGateway
class, and implement the required methods.
Payment Gateways in app/PaymentGateways
will be automatically registered by Cargo. They can then be referenced in the cargo.php
config file using their handle:
// config/statamic/cargo.php
'payments' => [
'gateways' => [
'custom_payment_gateway' => [
// Any config options...
],
],
],
Payment Form
As explained in the Checkout section above, each payment gateway has its own checkout URL, which can either be used as a return/callback URL, or can be submitted to using a <form>
, if needed.
<div id="payment-details">
<script>
customPaymentGateway.init({
return_url: '{{ checkout_url }}',
});
</script>
The gateway's setup
method should return anything you need in the payment form.
You shouldn't return any sensitive API keys though, as they will be available using Cargo's JSON API endpoint.
Webhooks
Each payment gateway is assigned a webhook URL, usually in the format of /!/cargo/payments/gatway_name/webhook
.
Shipping
After migrating to Cargo, you'll need to re-configure your site's shipping methods in the cargo.php
config file:
// config/statamic/cargo.php
'shipping' => [
'methods' => [
'free_shipping' => [],
],
],
Custom shipping methods
You should be able to re-use most of your existing code. It'll just need to be adjusted to work with Cargo's APIs.
API Changes
Shipping Methods should extend Cargo's abstract ShippingMethod
class, and implement the required methods.
Unlike Simple Commerce, shipping methods can return multiple shipping options, each with their own price.
Notifications
When you ran the cargo:install
command at the start of the migration process, you may have noticed it created a mailable in app/Mail
, a view in resources/views/emails
and added an event listener to your `AppServiceProvider.
Instead of notifications being configured in the cargo.php
config file, you're now responsible for the code which sends notifications to customers.
// app/Providers/AppServiceProvider.php
use App\Mail\OrderConfirmation;
use DuncanMcClean\Cargo\Events\OrderPaymentReceived;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Mail;
Event::listen(OrderPaymentReceived::class, function ($event) {
Mail::to($event->order->customer())
->locale($event->order->site()->shortLocale())
->send(new OrderConfirmation($event->order));
});
This gives you full control over how & when emails (or other kinds of notifications) are sent to customers, and does away with the whole palavar of publishing files and extending files in Simple Commerce.
To learn more about event listeners and mailables, please consult the Laravel documentation.
PHP APIs
While most things are in roughly the same place as they used to be in Simple Commerce, there are some pretty big things you should be aware of.
Namespace
The most obvious change is that you'll need to reference Cargo
in any imports instead of SimpleCommerce
.
It's a pretty easy find & replace:
- *Before:
DuncanMcClean\SimpleCommerce
- *After:
DuncanMcClean\Cargo
Events
If you're listening to any of Simple Commerce's events, you will need to listen for Cargo's equivalent events.
Old | New |
---|---|
DuncanMcClean\SimpleCommerce\Events\CouponRedeemed |
DuncanMcClean\Cargo\Events\DiscountRedeemed |
DuncanMcClean\SimpleCommerce\Events\DigitalDownloadReady |
Removed. You can link to product downloads from the order confirmation email instead. |
DuncanMcClean\SimpleCommerce\Events\GatewayWebhookReceived |
Removed. |
DuncanMcClean\SimpleCommerce\Events\OrderPaymentFailed |
Removed. |
DuncanMcClean\SimpleCommerce\Events\OrderSaved |
DuncanMcClean\Cargo\Events\OrderSaved |
DuncanMcClean\SimpleCommerce\Events\OrderStatusUpdated |
Removed. Can be replaced with one of the following events: * DuncanMcClean\Cargo\Events\OrderCancelled * DuncanMcClean\Cargo\Events\OrderPaymentPending * DuncanMcClean\Cargo\Events\OrderPaymentReceived * DuncanMcClean\Cargo\Events\OrderRefunded * DuncanMcClean\Cargo\Events\OrderReturned * DuncanMcClean\Cargo\Events\OrderShipped |
DuncanMcClean\SimpleCommerce\Events\PaymentStatusUpdated |
Removed. Can be replaced with one of the following events: * DuncanMcClean\Cargo\Events\OrderCancelled * DuncanMcClean\Cargo\Events\OrderPaymentPending * DuncanMcClean\Cargo\Events\OrderPaymentReceived * DuncanMcClean\Cargo\Events\OrderRefunded * DuncanMcClean\Cargo\Events\OrderReturned * DuncanMcClean\Cargo\Events\OrderShipped |
DuncanMcClean\SimpleCommerce\Events\PostCheckout |
Removed. |
DuncanMcClean\SimpleCommerce\Events\PreCheckout |
Removed. |
DuncanMcClean\SimpleCommerce\Events\StockRunOut |
DuncanMcClean\Cargo\Events\ProductNoStockRemaining |
DuncanMcClean\SimpleCommerce\Events\StockRunningLow |
DuncanMcClean\Cargo\Events\ProductStockLow |
For a full list of events, please consult the Events page.
Products
Like Simple Commerce, Cargo has a Product
facade, allowing you to fetch products.
The Product
instances returned by Cargo's facade are thin wrappers around Statamic's Entry
class. They add some handy helper methods around things like product variants, stock, and taxation.
While you can use Cargo's Product
facade in your own code, we would recommend using Statamic's Entry
repository directly instead.
Carts
As mentioned earlier in this guide, carts and orders are now stored separately. You can use the Cart
facade to find, query and create new carts:
use DuncanMcClean\Cargo\Facades\Cart;
// Find a cart
Cart::find(123);
// Query carts by customer
Cart::query()
->where('customer', 'user-id')
->get();
// Make and save a Cart instance
Cart::make()
->orderNumber(1234)
->save();
To find out more about the Cart
facade and its available methods, please visit the PHP APIs page.
Orders
Like Simple Commerce, Cargo provides an Order
facade, allowing you to find, query and create new orders.
We've documented some of the major changes to the Order
facade below...
Order Statuses
Order Statuses have been simplified in Cargo. The ->orderStatus()
and ->paymentStatus()
methods have been removed.
Instead, you can get/set an orders's status using the ->status()
method:
$order->status(OrderStatus::PaymentReceived);
Cargo also removes the ->statusLog()
method which existed in Simple Commerce.
Discounting
As part of Cargo's overhaul to discounting, the ->coupon()
and ->redeemCoupon()
methods have been removed.
You should instead set the discount_code
key on the cart (not the order, as discounts can't be applied after checkout).
$cart->set('discount_code', 'BLACKFRIDAY')->save();
Line Items
Cargo removed the addLineItem
, updateLineItem
, removeLineItem
and clearLineItem
methods, in favour of equivalent methods on the LineItems
collection:
// Add a line item
-$order->addLineItem([ +$order->lineItems()->create([ 'product' => 'product-id',
'quantity' => 1,
'total' => 1500,
]);
// Update a line item
-$order->updateLineItem($lineItemId, [ +$order->lineItems()->update($lineItemId, [ 'quantity' => 2,
]);
// Remove a line item
-$order->removeLineItem($lineItemId); +$order->lineItems()->remove($lineItemId);
// Clear all line items from the order
-$order->clearLineItems(); +$order->lineItems()->flush();
Customers
Cargo has significantly simplified the concept of customers. They are either users in Statamic, or guest customers whose information is stored on individual orders.
To associate an order with a user, pass either the User
object or their ID to the ->customer()
method:
$order->customer($user);
$order->customer($user->id());
To associate an order with a guest customer, pass an email with name
and email
keys to the ->customer()
method:
$order->customer([
'name' => 'David Hasselhoff',
]);
Totals
There's a couple of notable changes around order totals, and how order totals are calculated.
- The
->itemsTotal()
method has been renamed->subTotal()
. - The
->couponTotal()
method has been renamed->discountTotal()
. - Totals are now only calculated on carts. Once a cart has been converted to an order, the totals cannot be recalculated.
Payments
The gatewayData()
method has been removed. Payment Gateways are now responsible for adding payment details to the order data themselves.
Finally...
Once you're happy that everything has been migrated across successfully, there's a couple of post-migration cleanup steps you may want to take:
- Delete the
config/simple-commerce.php
file - Delete the
content/simple-commerce
directory - If you were storing customers and orders as entries, you can delete the "Customers" and "Orders" collections.
- If you were storing customers and orders in the database, you can drop the
customers
andorders
tables.- You can also remove the models from the
runway.php
config. If you're not using Runway elsewhere, you can also uninstall Runway:
composer remove statamic-rad-pack/runway - You can also remove the models from the
The End
I know the "Simple Commerce -> Cargo" migration has been a bit of a slog, so thank you for sticking with it! ๐
Cargo has been months of hard work, during evenings and weekends. It would make my dayweek if you would star the repository on GitHub ๐.