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
| Facade | Action |
|---|---|
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 cryptoBy 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.