Skip to content

Architecture v26.7+

The API is built on API Platform (Symfony) integrated with Maho Commerce (PHP 8.3+, fork of OpenMage/Magento 1).

  • Entry point: public/rest.php, bootstraps Maho, then hands off to Symfony
  • Resources: PHP 8 #[ApiResource] DTOs, all extend \Maho\ApiPlatform\Resource
  • Providers: State providers (read operations), all extend \Maho\ApiPlatform\Provider
  • Processors: State processors (write operations), all extend \Maho\ApiPlatform\Processor
  • Event listeners: Symfony listeners for cross-cutting concerns (caching, idempotency)
  • Authentication: JWT (HS256) via Firebase JWT library

Module structure:

app/code/core/Maho/ApiPlatform/
├── symfony/src/
│   ├── Resource.php         # Base class for all DTOs ($extensions)
│   ├── Provider.php         # Base class for all providers (auth + pagination)
│   ├── Processor.php        # Base class for all processors (auth + persistence)
│   ├── Trait/               # Opt-in traits (ProductLoader, Cache, ActivityLog, StoreAccess)
│   ├── Service/             # Shared services (StoreContext, mappers, etc.)
│   ├── Security/            # Authentication (JWT, OAuth2, user providers)
│   ├── EventListener/       # Cross-cutting concerns
│   └── ...
├── docs/                    # This documentation
├── etc/config.xml           # Module config
└── sql/                     # DB migration scripts

app/code/core/Mage|Maho/*/Api/  # Per-module API resources
├── {Entity}.php             # DTO (extends \Maho\ApiPlatform\Resource)
├── {Entity}Provider.php     # State provider (extends \Maho\ApiPlatform\Provider)
└── {Entity}Processor.php    # State processor (extends \Maho\ApiPlatform\Processor)

Base Classes

All API classes extend one of three base classes in Maho\ApiPlatform:

Resource

Base class for all DTOs. Provides the $extensions property for the event-based extension system.

#[ApiResource(...)]
class MyResource extends \Maho\ApiPlatform\Resource
{
    public ?int $id = null;
    public string $name = '';
    // $extensions is inherited from the base class
}

Provider

Base class for all state providers. Bundles authentication (via AuthenticationTrait) and pagination (via PaginationTrait). Provides a Security constructor that subclasses can call via parent::__construct($security).

final class MyProvider extends \Maho\ApiPlatform\Provider
{
    #[\Override]
    public function provide(Operation $operation, array $uriVariables = [], array $context = []): mixed
    {
        // Authentication methods available: isAdmin(), requireAuthentication(), etc.
        // Pagination available: $this->extractPagination($context)
    }
}

Processor

Base class for all state processors. Bundles authentication (via AuthenticationTrait) and model persistence (via ModelPersistenceTrait). Provides safeSave(), safeDelete(), secureAreaDelete(), and loadOrFail().

final class MyProcessor extends \Maho\ApiPlatform\Processor
{
    #[\Override]
    public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed
    {
        $user = $this->getAuthorizedUser();
        $this->requirePermission($user, 'myresource/write');

        $model = Mage::getModel('mymodule/entity');
        $model->setData([...]);
        $this->safeSave($model, 'create entity');
    }
}

Opt-in Traits

Domain-specific traits that can be added to providers or processors as needed:

Trait Purpose Used by
ProductLoaderTrait Loads a product by ID with store context and optional type constraint Catalog sub-resource providers/processors
CacheTrait Cache-aside remember() helper for provider responses ReviewProvider
ActivityLogTrait Logs write operations to the admin activity log Product, Category, CMS, Blog processors
StoreAccessTrait Resolves store codes to IDs and validates store-level access CMS and Blog processors

Shared Services

Live under app/code/core/Maho/ApiPlatform/symfony/Service/:

Service Purpose
StoreContext Store scope management, ensureStore(), getStoreId(), storeIdsToStoreCodes(), isAvailableForStore()
JwtService JWT issuance/validation for customer and API-user tokens
TokenBlacklist Tracks revoked JWT IDs (used by /auth/logout and on password change)
StoreDefaults Resolves default values per store (currency, locale, etc.) used during DTO building