Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Oc Mall Plugin Laravel Package

offline/oc-mall-plugin

Mall is a full-featured e-commerce plugin for October CMS built on Laravel. It adds products, variants, carts, orders, payments, discounts, tax and shipping handling, plus a customizable checkout and extensible Twig storefront components for building online shops quickly.

View on GitHub
Deep Wiki
Context7

Getting Started

offline/oc-mall-plugin is the October CMS integration for the offline/mall e-commerce package. Treat it as "Mall for October": the core commerce logic lives in the underlying Laravel package, and this plugin wires it into October's backend menus, CMS components, settings, and mail templating.

Version choice first. As of v2.0.0 the plugin requires October 2+. If you are still on October 1, you must stay on the ^1.0 line — ^2.0 will not install or run there. Pin explicitly rather than relying on ^ resolution:

# October 2+
composer require offline/oc-mall-plugin:^2.0

# October 1 (legacy)
composer require offline/oc-mall-plugin:^1.0

Then:

php artisan october:migrate

Open the backend Mall menu. This is where you will spend most of your first day: create a category, create a product with at least one variant, set a price and tax class, and publish it. Before the frontend works, configure Settings → Mall: currency/locale, tax classes and rates, shipping methods, payment methods, and order statuses.

Where to look first:

  1. plugins/offline/mall/ (or vendor/offline/oc-mall-plugin/) — read Plugin.php, components/, classes/, and models/ to understand what is exposed.
  2. The Mall backend menu — products, variants, categories, orders, discounts, settings.
  3. The bundled demo/theme docs — the README links to the official docs and a demo theme; copy the CMS component wiring from there rather than guessing.

First real use case: build a product page and cart. Add the Product and Cart components to a CMS page/partial, render the product and its variants, and use October AJAX handlers to add to cart:

{% component 'Product' %}
{% component 'Cart' %}
$cart = \OFFLINE\Mall\Facades\Mall::cart();
$cartItem = $cart->add($variant, 2); // variant-aware

Once add-to-cart works, move to the Checkout component and a test payment method (offline/invoice is the easiest). That sequence — catalog → cart → checkout → order in backend — is the fastest way to validate the whole install.

Implementation Patterns

Catalog and variants

Mall separates Product from Variant. Stock, SKU, and often price overrides live on the variant. Model prices as integer minor units (cents) and always format through Mall's money helpers rather than raw number formatting. If a product has no variants, Mall still exposes a default variant behavior, but be explicit in your Twig and PHP code: $product->variants vs $product->price.

Cart via the facade, not session globals

Do not reach into the session for cart data. Use:

use OFFLINE\Mall\Facades\Mall;

$cart = Mall::cart();
$cart->add($variant, $quantity);
$cart->remove($cartItem);
$cart->updateQuantity($cartItem, 3);

Cart data is session-backed, so any route or component that touches it must run inside October's web middleware/session stack. This is the most common source of "cart is empty on AJAX" bugs.

Checkout and order creation

The Checkout component handles address collection, shipping selection, payment selection, and order creation. For custom checkouts, reuse Mall's cart/order services rather than hand-rolling Order records — order creation triggers inventory reduction, discount application, tax recalculation, and mail dispatch.

Orders follow a status flow configurable in settings. Hook into it with events:

Event::listen('mall.order.created', function ($order) {
    // push to ERP, send Slack notification, etc.
});

Event::listen('mall.order.status.changed', function ($order, $previousStatus) {
    //
});

Payments and shipping as extension points

Custom payment gateways extend Mall's payment method base class and implement the process/redirect/webhook lifecycle. Custom shipping methods extend the shipping method base class and return rates for a given cart/address. Register them through the backend settings so shop admins can enable them per store.

Webhooks are the tricky part: your gateway's callback route must be publicly reachable, excluded from CSRF where appropriate, and must resolve the correct Order and Payment record. Test with the gateway's sandbox and a real HTTPS tunnel — localhost-only testing hides signature/URL bugs.

Extending models without forking

Use October's Model::extend() in your own plugin's boot() method:

\OFFLINE\Mall\Models\Product::extend(function ($model) {
    $model->addDynamicMethod('isFeatured', fn () => $model->featured);
});

Add fields via a migration in your own plugin, then extend the backend form YAML with $model->bindEvent('backend.form.extendFields', ...) or October's standard form extension config. Never edit files inside vendor/ or the plugin directory if it is Composer-managed.

Discounts and coupons

Mall supports discounts and coupon codes. Prefer configuring them in the backend over hard-coding price logic. If you need custom eligibility rules, extend the discount classes/events rather than mutating cart totals directly — manual total mutations get overwritten by Mall's recalculation on the next cart operation.

Frontend integration

Mall ships Twig components (Product, ProductList, Category, Cart, Checkout, address/account components). Use October's AJAX framework for cart interactions so partials re-render correctly. Keep cart/checkout partials small and re-render only the changed region; full-page reloads on quantity changes make the checkout feel broken.

Upgrading 1.x → 2.x

v2.0.0 is a platform bump, not a feature release. The only substantive change beyond the October 2 requirement is a fix for issues with newer Laravel versions. That means:

  • The day-to-day API — Mall::cart(), Twig components, events, model extension — is unchanged, so existing integrations should carry over without code rewrites.
  • The real work is the October 1 → October 2 migration itself (October's own upgrade guide, plugin/theme compatibility, PHP version floor).
  • Because the Laravel compatibility fix landed here, 1.x on newer Laravel/October 2 is a dead end — if you are hitting framework-level breakage, upgrading the plugin is the fix, not patching 1.x.
  • Treat it as a coordinated upgrade: bump October, the plugin, and your own plugins together on a staging clone, run migrations against a production data copy, then exercise the full catalog → cart → checkout → order flow before cutting over.

Gotchas and Tips

  • v2.0.0 is a hard platform boundary. October 1 shops must pin ^1.0; October 2 shops should pin ^2.0. Do not use a loose constraint and let Composer pick — a silent major bump across an October version boundary is an outage, not an upgrade.
  • Prices are integers. One of the most common early bugs is treating prices as floats. Use Mall's money helpers for display and keep arithmetic in minor units.
  • Tax and shipping recalculation is authoritative. Mall recalculates totals during cart/checkout transitions. Do not persist your own totals on the cart and expect them to survive.
  • Session middleware matters. Cart operations outside the standard web/session stack (custom API routes, queued jobs, console commands) will not see the cart. For headless/API use, pass an explicit cart or customer context rather than relying on session.
  • Stock lives on variants. Decrementing or checking stock on the product instead of the variant leads to overselling on multi-variant products.
  • Mail templates are per-locale and per-event. If order confirmation emails are missing, check Settings → Mall mail configuration and the locale of the order, not just config/mail.php.
  • Payment webhooks need real URLs. Configure the gateway callback URL with the public shop domain and verify signatures. Sandbox success pages are not a substitute for testing webhook delivery.
  • Composer-managed plugin = no direct edits. Anything you change in the plugin directory will be lost on update. Put customizations in your own plugin via events, Model::extend(), and backend form/list extensions. This matters more than ever across a major bump.
  • Cache invalidation after catalog changes. Cached category/product listings can serve stale prices or stock. Clear October's cache after bulk imports and after changing tax/shipping settings — and after the 2.x upgrade, since October 2's cache layer differs.
  • Version and platform drift. The release cadence here is slow and major versions track October majors, not calendar time. Before adopting, verify the plugin's PHP/Laravel/October constraints against your October version, read the v2.0.0 changelog (v1.16.2...v2.0.0), and test the full checkout flow on a staging clone. Pin the version in composer.json and budget time for compatibility patches — 2.x fixes newer-Laravel breakage but does not guarantee your other plugins are October 2-ready.
  • Debugging order/cart issues: log the relevant event payloads (mall.order.created, cart events) to storage/logs temporarily, and inspect the mall_orders, mall_order_items, and mall_carts tables directly. A surprising number of "totals are wrong" reports are stale cart rows or misassigned tax classes.
  • Currency formatting: do not use number_format directly on stored prices; use Mall's formatter so locale, currency symbol placement, and rounding stay consistent between cart, order emails, and backend.
  • Upgrade discipline: read the changelog and run migrations on a copy of production data. E-commerce schema changes affect live orders; never migrate production without a tested rollback. For the 2.x jump specifically, keep a rollback path to the 1.x database snapshot — October 2 migrations are not designed to be reversible in place.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment