Xgenious/ docs
Products
Get support

Theme Helper Functions

Themes provide a rich set of helper functions that abstract away route names and ensure theme code remains stable when the platform evolves. All route helpers are defined in core/app/Helpers/theme-frontend-helpers.php and follow the naming convention theme_*().

Warning

🚨 Never use route() directly in theme Blade files. Always use theme_*() helpers — they provide a stable API contract that protects your theme from route name changes.

Quick Reference by Category

FunctionReturnsNotes
theme_nav_menu($menuName, $itemClass)stringRender a WordPress menu with optional item CSS class.
theme_logo_html()stringRender the tenant's store logo with alt text.
theme_logo_url()stringGet the logo image URL (useful for favicon or OG tags).

Cart & Checkout

FunctionReturnsNotes
theme_cart_url()stringCart page URL.
theme_checkout_url()stringCheckout page URL.
theme_add_to_cart_url()stringAJAX endpoint for adding a product to cart.
theme_add_to_compare_url()stringAJAX endpoint for adding a product to compare list.
theme_add_to_wishlist_url()stringAJAX endpoint for adding a product to wishlist.
theme_remove_from_wishlist_url()stringAJAX endpoint for removing from wishlist.
theme_cart_count()intCurrent cart item count.
theme_wishlist_count()intCurrent wishlist item count.

Products & Catalog

FunctionReturnsNotes
theme_shop_url($page)stringShop listing page URL, optionally with page number.
theme_product_url(Product $product)stringURL to a specific product detail page.
theme_product_review_url(Product $product)stringAJAX endpoint for submitting a product review.
theme_compare_page_url()stringProduct compare page URL.
theme_category_url(Category $cat)stringCategory listing page URL.
theme_subcategory_url($subCat)stringSubcategory listing page URL.
theme_brand_url(Brand $brand)stringBrand page URL.
theme_tag_url(Tag $tag)stringTag archive page URL.

Site Identity

FunctionReturnsNotes
theme_site_name()stringStore name (tenant's site title).
theme_site_description()stringStore tagline/description.
theme_site_url()stringStore home page URL.
theme_home_url()stringTenant home page URL (may differ from shop home).

Authentication & User

FunctionReturnsNotes
theme_is_logged_in()booltrue when a customer is logged in.
theme_auth()User|nullCurrent logged-in customer, or null.
theme_login_url()stringLogin page URL.
theme_register_url()stringRegistration page URL.
theme_logout_url()stringLogout URL.
theme_user_dashboard_url()stringCustomer account dashboard URL.

Search & AJAX

FunctionReturnsNotes
theme_search_ajax_url()stringAJAX endpoint for live search.

Digital Products

FunctionReturnsNotes
theme_digital_shop_url()stringDigital product shop URL.
theme_digital_product_add_to_cart_url()stringAJAX endpoint for digital product add-to-cart.
theme_digital_product_review_url()stringAJAX endpoint for digital product review.

User Dashboard

FunctionReturnsNotes
theme_user_password_change_url()stringAJAX endpoint for password change submission.
theme_user_profile_update_url()stringAJAX endpoint for profile update.
theme_user_address_update_url()stringAJAX endpoint for address update.
theme_user_manage_account_url()stringLink to manage account page.
theme_user_downloads_url()stringLink to downloads page.
theme_user_tickets_url()stringLink to support tickets page.
theme_state_search_url()stringAJAX endpoint for state autocomplete.

Package & Invoice

FunctionReturnsNotes
theme_package_order_confirm_url($packageId)stringLink to confirm/pay for package order.
theme_package_order_cancel_url()stringAJAX endpoint for package order cancellation.
theme_package_invoice_url()stringAJAX endpoint for invoice generation.

Usage in Blade Views

<!-- Navigation Link -->
<a href="{{ theme_shop_url() }}">Shop</a>

<!-- AJAX Add to Cart -->
$.post('{{ theme_add_to_cart_url() }}', formData, function(r){
  if(r.status === 'success') toastr.success('Added to cart');
});

<!-- User State Display -->
@if(theme_is_logged_in())
  Welcome, {{ theme_auth()->name }}!
@endif

Usage in Controllers

// In a plugin controller needing theme routes:
return redirect(theme_shop_url());
Warning

💡 All theme helpers are defined with if (!function_exists(...)) guards, allowing themes to override them in their own service providers. Overrides take precedence and are never replaced by subsequent includes.

Error Handling & Isolation

Nazmart wraps all plugin execution in isolation boundaries to prevent a broken plugin from crashing the entire application.

  • boot() isolation — Each plugin's boot() is wrapped in try/catch. One broken plugin never halts the boot sequence.
  • Hook isolation — Each hook callback is individually wrapped. An exception in one callback does not prevent other callbacks on the same hook from running.
  • Lifecycle isolationon_activate() and on_deactivate() errors are caught and logged independently.
  • Dependency failures — If a plugin listed in requires is not active, the dependent plugin is skipped with a warning log entry rather than an exception.

Logging

All plugin errors are written to the plugin log channel:

# Check for boot errors
tail -f storage/logs/plugin.log

# Filter for a specific plugin
grep "acme-seo" storage/logs/plugin.log
Warning

💡 During development, set APP_ENV=local to disable the plugin manifest cache (60s TTL in production). This ensures your plugin.json changes are picked up immediately without running cache:clear.

Full Plugin Example

A complete, production-ready plugin demonstrating all major features: menus, hooks, filters, settings, shortcodes, and price plan integration.

plugin.json

{
  "id":                   "acme-loyalty",
  "name":                 "Acme Loyalty Points",
  "version":              "1.0.0",
  "description":         "Loyalty points system for tenant shops",
  "type":                 "tenant",
  "pricing":              "free",
  "min_platform_version": "2.5.0",
  "main":                 "src/AcmeLoyaltyPlugin.php",
  "author":               "Acme Corp"
}

src/AcmeLoyaltyPlugin.php

<?php
namespace Modules\AcmeLoyalty\Src;

use App\PluginSystem\PluginBase;

class AcmeLoyaltyPlugin extends PluginBase
{
    public function id(): string
    {
        return 'acme-loyalty';
    }

    public function boot(): void
    {
        // Register admin sidebar menu
        $this->add_menu([
            'id'      => 'acme-loyalty-menu',
            'label'   => __('Loyalty Points'),
            'icon'    => 'mdi-star',
            'route'   => 'tenant.admin.acme.loyalty.index',
            'order'   => 80,
            'context' => 'tenant',
        ]);

        // Award points when an order completes
        $this->add_action('nazmart:order_completed', function ($order) {
            $rate   = $this->get_option('points_per_dollar', 1);
            $points = (int) ($order->grand_total * $rate);
            // persist $points to acme_loyalty_points table...
        });

        // Optionally modify the displayed price
        $this->add_filter('nazmart:product_price', function ($price, $product) {
            // return price as-is (or modify for discounts)
            return $price;
        }, 10, 2);

        // Register plugin settings
        $this->register_settings([
            ['key' => 'points_per_dollar', 'label' => 'Points per $1 spent',    'type' => 'number',  'default' => 1],
            ['key' => 'welcome_bonus',     'label' => 'Welcome bonus points',     'type' => 'number',  'default' => 100],
            ['key' => 'enabled',           'label' => 'Enable loyalty program', 'type' => 'toggle',  'default' => true],
        ]);

        // Register [loyalty_balance /] shortcode
        $this->register_shortcode('loyalty_balance', function ($attrs) {
            $user = auth()->user();
            if (!$user) return '';
            return '<span class="loyalty-points">' . ($user->loyalty_points ?? 0) . ' pts</span>';
        });

        // Register as a price plan feature
        $this->add_filter('nazmart:price_plan_features', function (array $features): array {
            $features['acmeloyalty'] = __('Loyalty Points');
            return $features;
        });
    }

    public function on_activate(): void
    {
        // Run migrations — creates acme_loyalty_points table
        $this->run_migrations();
    }
}

Tips & Gotchas

Warning

⚠️ Booting order: All plugins boot before any HTTP request is handled. Do not rely on request context (query params, session, auth) inside boot(). Register callbacks; let them execute at the right time.

Warning

⚠️ Tenant context in boot(): tenant() may return null during certain CLI commands (queue workers, schedule, etc.). Always null-check before accessing tenant properties.

Warning

⚠️ Filter return values: Filters MUST return a value. Forgetting return $value silently passes null to the next filter in the chain and can break core functionality.

Warning

💡 Hook priority: Use priority < 10 to run before core hooks, > 10 to run after. When two plugins register at the same priority, registration order determines execution order.

Warning

💡 Asset handles: Handles must be globally unique across all plugins. Always prefix with your plugin ID: acme-loyalty-styles, acme-loyalty-script.

Note

ℹ️ Settings scope: get_option() in tenant context automatically fetches tenant-scoped values. Landlord-set values serve as global defaults when no tenant override exists.

Note

ℹ️ Route registration: Use register_web_routes() for tenant-facing frontend/dashboard pages (the platform calls this after tenancy is initialized). Use register_api_routes() for /api/v1/plugins/{id}/ endpoints. Landlord admin routes are registered by your Module's own ServiceProvider as usual.

Warning

💡 Cache: The plugin manifest is cached for 60 seconds in production, disabled in local env. After editing plugin.json, run php artisan cache:clear to pick up changes immediately.

Warning

💡 Viewing logs: Run tail -f storage/logs/plugin.log to watch plugin boot and hook errors in real time. Each log entry includes the plugin ID and hook name for easy filtering.

Still stuck?
Our support team is ready to help you get set up.
Get support