NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Shops for Laravel

DI and actions

There are three equivalent entry points; pick per call site. The Shops facade is the shortest and the recommended default. RoundlyConsulting\Shops\ShopsManager is the facade root — a container singleton you inject through the constructor for the same API as an explicit dependency, with no static calls. And every operation is a single-purpose action class with an execute() method, for composing into your own actions, queued jobs and commands.

Inject the manager

Every manager call resolves its action from the container, so your own bindings apply:

use Illuminate\Http\Request;
use RoundlyConsulting\Shops\Cart\Cart;
use RoundlyConsulting\Shops\Orders\DataTransferObjects\PlaceOrderData;
use RoundlyConsulting\Shops\Orders\Order;
use RoundlyConsulting\Shops\ShopsManager;

final class CheckoutController
{
    public function __construct(private ShopsManager $shops) {}

    public function __invoke(Request $request, Cart $cart): Order
    {
        return $this->shops->cart($cart)->checkout(PlaceOrderData::fromAddressBook($request->user()));
    }
}

Call the actions

use RoundlyConsulting\Shops\Actions\Cart\AddToCartAction;
use RoundlyConsulting\Shops\Actions\Inventory\AdjustStockAction;
use RoundlyConsulting\Shops\Actions\Orders\PlaceOrderAction;
use RoundlyConsulting\Shops\Inventory\Enums\StockReason;
use RoundlyConsulting\Shops\Orders\DataTransferObjects\PlaceOrderData;

app(AddToCartAction::class)->execute($cart, $variant, 2);
app(PlaceOrderAction::class)->execute($cart, new PlaceOrderData);
app(AdjustStockAction::class)->execute($variant, 10, StockReason::Received, $purchaseOrder, 'PO-17');

Facade method → action

FacadeAction
cart()->add()Actions\Cart\AddToCartAction
cart()->update()Actions\Cart\UpdateCartItemAction
cart()->remove()Actions\Cart\RemoveFromCartAction
cart()->clear()Actions\Cart\ClearCartAction
cart()->checkout()Actions\Orders\PlaceOrderAction
order()->transition() / cancel() / refund() / fulfil()Actions\Orders\TransitionOrderStatusAction
order()->charge()Actions\Orders\ChargeOrderAction
order()->quoteShipping()Actions\Orders\QuoteShippingAction
inventory()->receive() / returned() / adjust()Actions\Inventory\AdjustStockAction
  • Shops::fake() swaps in ShopsFake, a subtype of ShopsManager, so constructor-injected managers get the fake too — and so do the model methods, which call the manager.
  • An action you call directly bypasses the manager, so the fake does not record it.
  • Checkout takes the PlaceOrderData DTO — build it by hand or with PlaceOrderData::fromAddressBook($customer).
  • AddOrderItemAction, ReserveStockAction and ReleaseStockAction are @internal — building blocks of checkout and the cancel and fulfil transitions, not for host use.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.