Skip to main content

Working with Orders

Orders are represented by the StoreEngine\Classes\Order object, which wraps a row in the wp_storeengine_orders table (see Database Schema). Order extends AbstractOrder (a table-backed AbstractEntity), so it has full CRUD plus commerce-specific behavior.

Subscriptions reuse this machinery — Subscription extends Order — so everything here applies to them too. See Subscriptions.

Loading an order

Pass an id to the constructor to load; pass 0 (the default) for a blank, unsaved order:

use StoreEngine\Classes\Order;

$order = new Order( 123 ); // load existing order #123
$blank = new Order(); // blank order, not yet persisted

if ( $order->get_id() ) {
echo $order->get_status();
echo $order->get_formatted_order_total();
}

You can also look an order up by key or meta:

$order = ( new Order() )->get_by_key( $order_key );
$order = ( new Order() )->get_by_meta( '_external_ref', 'INV-2025-0091' );
There are no global helper functions

StoreEngine does not ship storeengine_get_order() style globals. Instantiate Order directly.

Creating and saving

The lifecycle mirrors a typical active-record object. save() inserts when the order has no id and updates otherwise:

use StoreEngine\Classes\Order;
use StoreEngine\Utils\Helper;

$order = new Order();
$order->set_currency( 'USD' );

$product = Helper::get_product( 42 );
$price = $product->get_prices()[0]; // a Price object

$order->add_product( $price, 2 ); // add 2 units of this price
$order->add_fee( 'Handling', 5.00 );

$order->save(); // persist; assigns an id

echo $order->get_id();
echo $order->get_order_number();

CRUD methods available on the object:

MethodDescription
create()Insert a new row.
update()Persist changes to an existing row.
save()Insert or update as appropriate.
delete( bool $force = false )Trash, or permanently delete when $force is true.
get_by_key( string $key )Load by the order key.
get_by_meta( $key, $value, $format = null )Load by a meta value.

Reading order data

Getters accept a $context of 'view' (default, filtered for display) or 'edit' (raw). Date getters return a StoreEngine\Classes\StoreEngineDateTime.

MethodReturns
get_id()Order id.
get_status( $context = 'view' )Current status slug.
get_order_number()Human-readable order number.
get_user_id()Customer WP user id.
get_currency()Currency code.
get_total()Grand total.
get_subtotal()Items subtotal.
get_total_tax() / get_tax_totals()Tax total / per-rate breakdown.
get_shipping_total()Shipping total.
get_discount_total()Total discounts.
get_prices_include_tax()Whether stored prices are tax-inclusive.
get_formatted_order_total()Display-formatted total.
get_date_created() / get_date_paid() / get_date_completed()Key dates.
get_payment_method() / get_transaction_id()Payment details.
get_billing_first_name() … / get_shipping_country()Address fields.
is_paid()Whether payment has completed.

The items model

An order is a set of typed line rows in wp_storeengine_order_items. get_items() defaults to line_item (products); pass a type or use the typed helpers:

$product_lines = $order->get_line_product_items();
$tax_lines = $order->get_line_tax_items();
$shipping = $order->get_line_shipping_items();
$fees = $order->get_line_fee_items();
$coupon_lines = $order->get_line_coupon_items();

$count = $order->get_item_count();
$codes = $order->get_coupon_codes();
Row typeRetrieved via
line_item (product)get_line_product_items() / get_items()
taxget_line_tax_items()
shippingget_line_shipping_items()
feeget_line_fee_items() / get_fees()
couponget_line_coupon_items() / get_coupons()

Mutating items

$item_id = $order->add_product( $price, 1 ); // $price is a Price object
$order->add_fee( 'Gift wrap', 3.50 );
$order->apply_coupon( 'WELCOME10' );
$order->recalculate_coupons();
$order->remove_coupon( 'WELCOME10' );
$order->remove_item( $item_id );
$order->save();

add_product() takes a Price object, not a product id — the price is the purchasable unit. See Products and Cart for the price/price_id model.

Changing status

Two methods change an order's status. Prefer update_status() — it runs the transition, records a note, and persists in one call:

// Transition + note + save, in one call.
$order->update_status( 'processing', 'Stock allocated.' );

// Lower-level: set the status field (returns [from, to]); you save yourself.
[ $from, $to ] = $order->set_status( 'on_hold' );
$order->save();
MethodBehavior
update_status( string $new, string $note = '', bool $manual = false )Transitions, notes, and saves. Returns bool.
set_status( string $new, string $note = '', bool $manual = false )Sets the status field, returns [from, to]. Does not save on its own.

Valid statuses and allowed transitions are governed by the status state machine — see Order Statuses.

Completing payment

When a gateway confirms payment, call payment_complete(). It moves the order to a paid state, stamps the paid date, and records the transaction id:

$order->payment_complete( $gateway_transaction_id );

if ( $order->is_paid() ) {
// fulfill
}

To force an order to paid regardless of gateway state (e.g. manual/offline payment reconciliation):

$order->mark_as_paid_force( 'Marked paid manually after bank transfer.' );

See also