Upgrade Guide: v2.4 to v3.0

Overview

Simple Commerce v3.0 comes with a bunch of new features, including some big quality of life improvements, for both developers and back-office users. In addition, there's a number of breaking changes, especially if you're doing custom 'things' with Simple Commerce.

To get started with the upgrade process, follow the below steps:

1. In your composer.json file, update the doublethreedigital/simple-commerce version constraint:

"doublethreedigital/simple-commerce": "3.0.*"
"doublethreedigital/simple-commerce": "3.0.*"

2. Then run:

composer update doublethreedigital/simple-commerce --with-dependencies
composer update doublethreedigital/simple-commerce --with-dependencies

3. You may also want to clear your route & view caches:

php artisan route:clear
php artisan view:clear
php artisan route:clear
php artisan view:clear

4. Simple Commerce will have attempted upgrading some things for you (config changes, blueprint updates, etc). However, it's highly likely you will need to make some manual changes, along with some testing. Please test before you push to production!

Changes

High: API Changes

Internally, a lot has changed in terms of how things are structured, how you access data, etc. If you've written any kind of custom code at all, you'll need to make some manual code changes.

I've noted all of the changes below - however, this isn't by far everything - you may review the related PR for more information.

Content Drivers

SC v3 changes the way 'content drivers' work. Instead of the driver being the Order/Customer class itself, it's a repository (which is inline with how Statamic does it). Essentially, if you need to use a database or third-party to store your data, you'd create a repository which implements the required methods, instead of creating an entire Order/Customer class - hopefully that explanation makes sense.

During the upgrade process, Simple Commerce should have updated your config to represent this change:

'content' => [
'coupons' => [
'repository' => \DuncanMcClean\SimpleCommerce\Coupons\EntryCouponRepository::class,
'collection' => 'coupons',
],
 
'customers' => [
'repository' => \DuncanMcClean\SimpleCommerce\Customers\EntryCustomerRepository::class,
'collection' => 'customers',
],
 
'orders' => [
'repository' => \DuncanMcClean\SimpleCommerce\Orders\EntryOrderRepository::class,
'collection' => 'orders',
],
 
'products' => [
'repository' => \DuncanMcClean\SimpleCommerce\Products\EntryProductRepository::class,
'collection' => 'products',
],
],
'content' => [
'coupons' => [
'repository' => \DuncanMcClean\SimpleCommerce\Coupons\EntryCouponRepository::class,
'collection' => 'coupons',
],
 
'customers' => [
'repository' => \DuncanMcClean\SimpleCommerce\Customers\EntryCustomerRepository::class,
'collection' => 'customers',
],
 
'orders' => [
'repository' => \DuncanMcClean\SimpleCommerce\Orders\EntryOrderRepository::class,
'collection' => 'orders',
],
 
'products' => [
'repository' => \DuncanMcClean\SimpleCommerce\Products\EntryProductRepository::class,
'collection' => 'products',
],
],

Important!

During the upgrade, SC will reset the 'repositories' to the new defaults. If you were using another content driver, you must re-configure this post-update.

If you were implementing a custom 'content driver' previously for something, you will need to review the changes and refactor your implementation. If it helps, here's a link to view the 'interfaces' behind SC's Data stuff.

Changes to how you access data

Along with content drivers working differently - how you access/save data will have also changed:

Creating Products/Customers/Orders/Coupons

Previously:

$order = Order::create([
'items' => [
[
'product' => 'abc',
'quantity' => 1,
'total' => 1255,
],
],
'items_total' => 1255,
'gift_note' => 'This is a very special note.',
]);
$order = Order::create([
'items' => [
[
'product' => 'abc',
'quantity' => 1,
'total' => 1255,
],
],
'items_total' => 1255,
'gift_note' => 'This is a very special note.',
]);

Now:

$order = Order::make()
->lineItems([
[
'product' => 'abc',
'quantity' => 1,
'total' => 1255,
],
])
->itemsTotal(1255)
->data([
'gift_note' => 'This is a very special note.',
]);
 
$order->save();
$order = Order::make()
->lineItems([
[
'product' => 'abc',
'quantity' => 1,
'total' => 1255,
],
])
->itemsTotal(1255)
->data([
'gift_note' => 'This is a very special note.',
]);
 
$order->save();

A lot of 'things' on Data Models are now properties which can be modified using fluent getter/setters. Anything outside of a property can be set using ->data(), ->set() or ->merge(). We're now using the same pattern for making/saving as Statamic itself.

Getting the 'grand total' from an order

Previously:

$order = Order::find('123');
 
$order->get('grand_total');
$order = Order::find('123');
 
$order->get('grand_total');

Now:

$order = Order::find('123');
 
$order->grandTotal();
$order = Order::find('123');
 
$order->grandTotal();

Getting the original entry

Previously:

$order = Order::find('123');
 
$order->entry();
$order = Order::find('123');
 
$order->entry();

Now:

$order = Order::find('123');
 
$order->resource();
$order = Order::find('123');
 
$order->resource();

Line Items

When accessing Line Items, you'll no longer receive an array, you'll now receive an instance of the LineItem class.

Previously:

$lineItem = $order->lineItems()->first();
 
$product = Product::find($lineItem['product']);
$quantity = $lineItem['quantity'];
$giftNote = $lineItem['metadata']['gift_note'];
$lineItem = $order->lineItems()->first();
 
$product = Product::find($lineItem['product']);
$quantity = $lineItem['quantity'];
$giftNote = $lineItem['metadata']['gift_note'];

Now:

$lineItem = $order->lineItems()->first();
 
$product = $lineItem->product();
$quantity = $lineItem->quantity();
$giftNote = $lineItem->metdata()->get('gift_note');
$lineItem = $order->lineItems()->first();
 
$product = $lineItem->product();
$quantity = $lineItem->quantity();
$giftNote = $lineItem->metdata()->get('gift_note');

Namespace changes

If you were previously referencing any of these classes, you should update your references to their new namespaces:

  • DuncanMcClean\SimpleCommerce\Support\Currency -> DuncanMcClean\SimpleCommerce\Currency
  • DuncanMcClean\SimpleCommerce\Support\Country -> DuncanMcClean\SimpleCommerce\Country
  • DuncanMcClean\SimpleCommerce\Support\Regions -> DuncanMcClean\SimpleCommerce\Regions

You should also note that any references to the Currency/Country/Region facades should now be updated to these new namespaces. The usage remains the same.

High: Field Whitelisting (Partially automated)

To improve the security of your site, we've introduced a 'whitelist' for the fields that will be saved from Simple Commerce's front-end forms.

Previously, Simple Commerce would save anything provided in a request (for example: on the request to add a product to the cart) to your order entry.

Now, Simple Commerce will only save the request data from the fields you've whitelisted in the Simple Commerce config.

// config/simple-commerce.php
 
/*
|--------------------------------------------------------------------------
| Field Whitelist
|--------------------------------------------------------------------------
|
| You may configure the fields you wish to be editable via front-end forms
| below. Wildcards are not accepted due to security concerns.
|
| https://simple-commerce.duncanmcclean.com/tags#field-whitelisting
|
*/
 
'field_whitelist' => [
'orders' => [
'shipping_name', 'shipping_address', 'shipping_address_line1', 'shipping_address_line2', 'shipping_city',
'shipping_region', 'shipping_postal_code', 'shipping_country', 'shipping_note', 'shipping_method',
'use_shipping_address_for_billing', 'billing_name', 'billing_address', 'billing_address_line2',
'billing_city', 'billing_region', 'billing_postal_code', 'billing_country',
],
 
'line_items' => [],
 
'customers' => ['name', 'email'],
],
// config/simple-commerce.php
 
/*
|--------------------------------------------------------------------------
| Field Whitelist
|--------------------------------------------------------------------------
|
| You may configure the fields you wish to be editable via front-end forms
| below. Wildcards are not accepted due to security concerns.
|
| https://simple-commerce.duncanmcclean.com/tags#field-whitelisting
|
*/
 
'field_whitelist' => [
'orders' => [
'shipping_name', 'shipping_address', 'shipping_address_line1', 'shipping_address_line2', 'shipping_city',
'shipping_region', 'shipping_postal_code', 'shipping_country', 'shipping_note', 'shipping_method',
'use_shipping_address_for_billing', 'billing_name', 'billing_address', 'billing_address_line2',
'billing_city', 'billing_region', 'billing_postal_code', 'billing_country',
],
 
'line_items' => [],
 
'customers' => ['name', 'email'],
],

This step should be partially automated during the upgrade process. After upgrading, you should see the field_whitelist array appear in your simple-commerce.php config file. Simple Commerce will have pulled any fields from your order blueprint that aren't 'reserved' (eg. fields like is_paid, they're ones you probably don't want users to be able to fill).

High: Shipping Method configs

Simple Commerce now allows for passing configuration arrays for shipping methods. However, for this to work, shipping methods must be updated to extend upon the BaseShippingMethod class provided by Simple Commerce.

<?php
 
namespace App\ShippingMethods;
 
use DuncanMcClean\SimpleCommerce\Contracts\ShippingMethod;
use DuncanMcClean\SimpleCommerce\Shipping\BaseShippingMethod;
 
class FirstClass extends BaseShippingMethod implements ShippingMethod
{
//
}
<?php
 
namespace App\ShippingMethods;
 
use DuncanMcClean\SimpleCommerce\Contracts\ShippingMethod;
use DuncanMcClean\SimpleCommerce\Shipping\BaseShippingMethod;
 
class FirstClass extends BaseShippingMethod implements ShippingMethod
{
//
}

If you wish to start passing in config variables to your shipping methods, you may do it like so:

'sites' => [
'default' => [
...
 
'shipping' => [
'methods' => [
\DuncanMcClean\SimpleCommerce\Shipping\StandardPost::class => [
'config' => 'setting',
'foo' => 'bar',
],
],
],
],
],
'sites' => [
'default' => [
...
 
'shipping' => [
'methods' => [
\DuncanMcClean\SimpleCommerce\Shipping\StandardPost::class => [
'config' => 'setting',
'foo' => 'bar',
],
],
],
],
],

And inside the shipping method, you may do $this->config()->get('key') to get a specific config value.

Medium: Order Emails

Previously, Simple Commerce would send a fairly basic email with a PDF receipt attached.

In v3, the receipt PDF has been removed from order emails. Instead, email body's contain a table with the order line items, along with any customer information which is displayed below.

Continue with previous behaviour

If you wish to continue using the previous behaviour (where you get a simple email, along with a PDF receipt), follow these steps:

  1. Copy the notification class from inside Simple Commerce and place it inside an app/Notifications folder. Keep the same filename.
  2. Change the namespace for the notification from SC's one to your App one:
<?php
 
namespace DuncanMcClean\SimpleCommerce\Notifications;
namespace App\Notifications;
 
use Barryvdh\DomPDF\Facade as PDF;
use DuncanMcClean\SimpleCommerce\Contracts\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
 
class CustomerOrderPaid extends Notification
{
<?php
 
namespace DuncanMcClean\SimpleCommerce\Notifications;
namespace App\Notifications;
 
use Barryvdh\DomPDF\Facade as PDF;
use DuncanMcClean\SimpleCommerce\Contracts\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
 
class CustomerOrderPaid extends Notification
{
  1. Next, you'll need to require the DomPDF library which is no longer required for you by Simple Commerce. DomPDF is the library which generates the receipt PDFs.
composer require dompdf/dompdf
composer require dompdf/dompdf
  1. Last but not least, update your Simple Commerce config file to use your copy of the built-in notifications.
// config/simple-commerce.php
 
'notifications' => [
'order_paid' => [
\DuncanMcClean\SimpleCommerce\Notifications\CustomerOrderPaid::class => [
\App\Notifications\CustomerOrderPaid::class => [
'to' => 'customer',
],
],
 
// ...
],
// config/simple-commerce.php
 
'notifications' => [
'order_paid' => [
\DuncanMcClean\SimpleCommerce\Notifications\CustomerOrderPaid::class => [
\App\Notifications\CustomerOrderPaid::class => [
'to' => 'customer',
],
],
 
// ...
],

Medium: Order Confirmation page

Although not technically a breaking change, it's worth noting as it may help to cleaup your code.

On the 'Order Confirmation' page (the one after checking out), you'd previously have to use the {{ session:cart }} tag in order to access the previous cart. However, now you may use Simple Commerce's cart tags like normal.

Previously:

{{ session:cart }}
Thanks for your order ({{ title }}), {{ customer:title }}
{{ /session:cart }}
{{ session:cart }}
Thanks for your order ({{ title }}), {{ customer:title }}
{{ /session:cart }}

Now:

{{ sc:cart }}
Thanks for your order ({{ title }}), {{ customer:title }}
{{ /sc:cart }}
{{ sc:cart }}
Thanks for your order ({{ title }}), {{ customer:title }}
{{ /sc:cart }}

Medium: Removed 'Sales Widget'

Simple Commerce v3.0 drops the Sales Widget which could optionally be added to your Control Panel Dashboard. It's now recommended to take advantage of the Overview page for this same (and more) functionality.

Low: Gateway & Shipping Method fields

During the upgrade process, Simple Commerce should have added two new fields to your Order blueprint. A Gateway field and a Shipping Method field. These fields should hopefully be useful for your CP users to be able to see the gateway/shipping method that's being used for an order.

The fields will automatically be pushed into the Sidebar of the Order blueprint, you may move it as you wish.

Note!

When using the Stripe Gateway, past orders will show 'Unknown' as the payment ID. Future orders will show the payment ID as expected - this is due to some data which was missing prior to v3.

Low: Higher System Requirements

Simple Commerce v3 requires you to be using PHP 8.0 (and above), along with Laravel 8 (and above) and Statamic 3.3. Adjusting the system requirements encourages developers to stay up to date and means Simple Commerce can take advantage of new features.

Low: Order Numbers (Automated)

In the past, order numbers would be stored as part of the title on Order entries.

However, SC v3 has taken advantage of a Statamic feature called 'title formats'. This means we store the order number in it's own field, order_number (hidden field, added during upgrade).

Then, Simple Commerce will configure the title format to be like so: #xxxx.

Running into an issue upgrading?

Like I say, quite a lot has changed between v2.4 and v3.0 so if you're running into issues upgrading, please either open a GitHub Issue or send me an email. I'll try and help as best I can.

Previous upgrade guides


You may also view a diff of changes between v2.4 and v3.0