A Comprehensive Guide to Developing Extensions for OpenCart 4

OpenCart is a popular open‑source eCommerce platform known for its flexibility and user‑friendliness. With the release of OpenCart 4, developers have new opportunities to enhance and extend the platform’s functionality. This guide provides a thorough, up‑to‑date walkthrough of developing an extension for OpenCart 4, covering planning, development, testing, and deployment-with current best practices for 2026.

TL;DR

  • OpenCart 4 extensions follow a self‑contained directory structure under /extension/{vendor}/, replacing the scattered file placement used in previous versions.
  • OpenCart 4.1.0.0 restored the OCMOD modification system after it was removed in early 4.0.x releases, giving developers a familiar way to modify core behaviour alongside the event system.
  • OpenCart 4.2 introduced Tasks – background processes for operations that do not require immediate feedback, similar to scheduled jobs or cron tasks.
  • The event system remains the primary extension mechanism for hooking into core functionality without modifying core files, with events triggered at key points in controllers, models, and views.
  • OpenCart 4 requires PHP 8.0+ and uses namespaced classes following an MVC‑A (Model‑View‑Controller‑Action) pattern.

Setting Up Your Development Environment

Before writing any code, set up a local development environment with the correct OpenCart version, a web server, and essential tools.

Installing OpenCart 4

  1. Download OpenCart 4: Obtain the latest stable version from the official OpenCart website. For 2026, this means version 4.1.x or newer.
  2. Extract files: Unzip the downloaded archive and place the contents in your web server’s document root or a local development directory.
  3. Create a database: Set up a new MySQL or MariaDB database for your OpenCart installation.
  4. Run the installer: Access the installation script via your browser and follow the on‑screen instructions. The installer checks for PHP version and extension requirements.

System Requirements

OpenCart 4 requires:

  • PHP 8.0 or higher (PHP 8.1+ recommended)
  • MySQL 5.6+ or MariaDB 10.1+
  • Web server: Apache with mod_rewrite or Nginx
  • Extensions: PDO, OpenSSL, cURL, JSON, XML, and GD
  • IDE: Visual Studio Code, PhpStorm, or Sublime Text with PHP and Twig support
  • Version control: Git for tracking changes
  • Local server: XAMPP, MAMP, Laravel Valet, or Docker (the official OpenCart Docker image is available)
  • Composer: Dependency manager used by OpenCart 4 core

Understanding OpenCart 4 Architecture

OpenCart 4 introduces significant changes compared to version 3, both in structure and in extension mechanisms.

MVC‑A (Model‑View‑Controller‑Action) Pattern

OpenCart 4 follows a custom MVC‑A pattern-Model‑View‑Controller‑Action-built on modern PHP 8.0+ with namespaced classes. The framework emphasises modularity, extensibility through events, and a clean separation of concerns.

ComponentResponsibility
ModelData access and business logic. Interacts with the database.
ViewUser interface and presentation. Uses the Twig templating engine.
ControllerProcesses user input, orchestrates models and views, and returns responses.
ActionThe specific method within a controller that handles a request.

Self‑Contained Extension Directory Structure

One of the most important changes in OpenCart 4 is the move to a self‑contained extension directory. In OpenCart 3, extension files were scattered across core directories like admin/controller/extension/module/. In OpenCart 4, your entire extension lives in a single folder under /extension/{vendor}/.

This structure makes extensions easier to develop, version, and maintain. The recommended structure is:

extension/
└── {vendor}/
 └── {extension_name}/
 ├── admin/
 │ ├── controller/
 │ ├── model/
 │ ├── view/
 │ │ └── template/
 │ └── language/
 ├── catalog/
 │ ├── controller/
 │ ├── model/
 │ ├── view/
 │ │ └── template/
 │ └── language/
 ├── system/
 │ └── library/ # For custom classes
 ├── install.sql # Database installation script
 ├── install.php # Installation logic
 └── uninstall.sql # Database uninstallation script

The root namespace for extension controllers follows the pattern:Opencart\Admin\Controller\Extension\{Vendor}\{ExtensionName}\{ControllerName}.

Extension Mechanisms: Events, OCMOD, and Tasks

OpenCart 4 provides three primary mechanisms for extending functionality.

Event System

The event system is the recommended way to extend OpenCart 4 without modifying core files. Events are triggered at key points in controller, model, and view execution. Extensions can register listeners that execute custom code when these events fire.

Events are registered in the extension’s installation method or via the Extension > Events admin interface. A typical event registration looks like:

// In your extension's install() method
$this->load->model('setting/event');
$this->model_setting_event->addEvent(
 'your_extension_code',
 'catalog/controller/common/header/before',
 'extension/your_vendor/your_extension/event/header'
);

Events are the primary extension mechanism for OpenCart 4, offering a cleaner and more secure alternative to file modifications.

OCMOD (OpenCart Modification System)

Status update for 2026: OCMOD was removed in early OpenCart 4.0.x releases, but was reintroduced in OpenCart 4.1.0.0. The official GitHub release for 4.1.0.0 explicitly states “ADDED OCMOD back!!”.

OCMOD allows developers to modify core OpenCart files through XML‑based modifications without directly editing the core code. It intercepts file loading requests and substitutes original files with modified versions if they exist.

For OpenCart 4.1.x and newer, OCMOD is available and can be used alongside the event system. For versions between 4.0.0.0 and 4.0.2.3, OCMOD is not supported-extensions must use the event system exclusively.

Practical guidance for 2026:

  • If you are targeting OpenCart 4.1.x or newer, you have both options available
  • For new extensions, prefer the event system over OCMOD where possible-it is more maintainable and less likely to cause conflicts
  • Use OCMOD only when you need to modify core behaviour that events cannot cover

Tasks (Introduced in OpenCart 4.2)

Tasks were introduced in OpenCart 4.2. They are background processes for operations that do not require immediate feedback, aiming to speed up the overall experience.

Tasks are ideal for:

  • Sending bulk emails
  • Generating reports
  • Synchronising data with external systems
  • Processing queued jobs

Tasks appear in the admin interface under Extension > Tasks after installation. They can be triggered manually or via cron jobs.

Developing Your Extension

Step 1: Plan Your Extension

Before writing code, define:

  • Purpose: What problem does your extension solve?
  • Features: What functionality will it provide?
  • User interface: Will it have admin settings? Does it modify the storefront?
  • Extension type: Module, payment gateway, shipping method, theme, or other.

Step 2: Create the Directory Structure

Create the necessary directories under /extension/{vendor}/{extension_name}/. For a simple module, you typically need:

extension/
└── yourvendor/
 └── examplemodule/
 ├── admin/
 │ ├── controller/
 │ │ └── module.php
 │ ├── model/
 │ │ └── module.php
 │ ├── view/
 │ │ └── template/
 │ │ └── module.twig
 │ └── language/
 │ └── en-gb/
 │ └── module.php
 ├── catalog/
 │ ├── controller/
 │ │ └── module.php
 │ ├── model/
 │ │ └── module.php
 │ ├── view/
 │ │ └── template/
 │ │ └── module.twig
 │ └── language/
 │ └── en-gb/
 │ └── module.php
 ├── install.sql
 └── install.php

Step 3: Write the Controller

The controller handles user requests and orchestrates the response. For an admin module controller, the file path would be:

extension/yourvendor/examplemodule/admin/controller/module.php

<?php
namespace Opencart\Admin\Controller\Extension\YourVendor\ExampleModule;
class Module extends \Opencart\System\Engine\Controller
{
 public function index(): void
 {
 $this->load->language('extension/yourvendor/examplemodule/module');
 $this->document->setTitle($this->language->get('heading_title'));
 $data['breadcrumbs'] = $this->getBreadcrumbs();
 // Load your settings from the database
 $data['module_status'] = $this->config->get('module_example_status');
 $data['header'] = $this->load->controller('common/header');
 $data['column_left'] = $this->load->controller('common/column_left');
 $data['footer'] = $this->load->controller('common/footer');
 $this->response->setOutput($this->load->view('extension/yourvendor/examplemodule/module', $data));
 }
 protected function getBreadcrumbs(): array
 {
 $breadcrumbs = [];
 $breadcrumbs[] = [
 'text' => $this->language->get('text_home'),
 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'])
 ];
 $breadcrumbs[] = [
 'text' => $this->language->get('text_extension'),
 'href' => $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=module')
 ];
 $breadcrumbs[] = [
 'text' => $this->language->get('heading_title'),
 'href' => $this->url->link('extension/yourvendor/examplemodule/module', 'user_token=' . $this->session->data['user_token'])
 ];
 return $breadcrumbs;
 }
}

Step 4: Write the Model

The model handles data access. For settings management:

extension/yourvendor/examplemodule/admin/model/module.php

<?php
namespace Opencart\Admin\Model\Extension\YourVendor\ExampleModule;
class Module extends \Opencart\System\Engine\Model
{
 public function install(): void
 {
 // Create database tables
 $this->db->query("
 CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "example_module` (
 `example_module_id` INT(11) NOT NULL AUTO_INCREMENT,
 `name` VARCHAR(255) NOT NULL,
 `status` TINYINT(1) NOT NULL DEFAULT 0,
 PRIMARY KEY (`example_module_id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
 ");
 }
 public function uninstall(): void
 {
 $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "example_module`;");
 }
 public function getSettings(): array
 {
 $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "example_module`");
 return $query->rows;
 }
}

Step 5: Write the View (Twig Template)

OpenCart 4 uses the Twig templating engine. Admin views go in the admin/view/template/ directory:

extension/yourvendor/examplemodule/admin/view/template/module.twig

{{ header }}{{ column_left }}
<div id="content">
 <div class="page-header">
 <div class="container-fluid">
 <div class="float-end">
 <button type="submit" form="form-module" data-toggle="tooltip" title="{{ button_save }}" class="btn btn-primary">
 <i class="fa-solid fa-save"></i>
 </button>
 <a href="{{ back }}" data-toggle="tooltip" title="{{ button_back }}" class="btn btn-light">
 <i class="fa-solid fa-reply"></i>
 </a>
 </div>
 <h1>{{ heading_title }}</h1>
 <ol class="breadcrumb">
 {% for breadcrumb in breadcrumbs %}
 <li class="breadcrumb-item">
 <a href="{{ breadcrumb.href }}">{{ breadcrumb.text }}</a>
 </li>
 {% endfor %}
 </ol>
 </div>
 </div>
 <div class="container-fluid">
 <div class="card">
 <div class="card-header"><i class="fa-solid fa-pencil"></i> {{ text_edit }}</div>
 <div class="card-body">
 <form id="form-module" method="post" action="{{ save }}" data-oc-toggle="ajax">
 <div class="row mb-3">
 <label class="col-sm-2 col-form-label" for="input-status">{{ entry_status }}</label>
 <div class="col-sm-10">
 <div class="form-check form-switch form-switch-lg">
 <input type="hidden" name="module_example_status" value="0"/>
 <input type="checkbox" name="module_example_status" value="1" id="input-status" class="form-check-input"{% if module_example_status %} checked{% endif %}/>
 </div>
 </div>
 </div>
 </form>
 </div>
 </div>
 </div>
</div>
{{ footer }}

Step 6: Write Language Files

Language files provide translations for your extension. For English:

extension/yourvendor/examplemodule/admin/language/en-gb/module.php

<?php
// Heading
$_['heading_title'] = 'Example Module';
// Text
$_['text_extension'] = 'Extensions';
$_['text_success'] = 'Success: You have modified Example Module!';
$_['text_edit'] = 'Edit Example Module';
$_['text_footer_message'] = 'This is an example module for OpenCart 4.';
// Entry
$_['entry_status'] = 'Status';
// Error
$_['error_permission'] = 'Warning: You do not have permission to modify Example Module!';

Step 7: Write Installation Script

OpenCart 4 looks for install.sql and install.php in the extension root. The install.php file is executed during installation and can set up events, create database tables, and initialise settings.

extension/yourvendor/examplemodule/install.php

<?php
// Install script for Example Module
$installer = $this;
$installer->load->model('setting/event');
// Register an event listener
$installer->model_setting_event->addEvent(
 'example_module',
 'catalog/controller/common/header/before',
 'extension/yourvendor/examplemodule/event/header'
);

Step 8: Register Events

For the event system to work, your extension must register event listeners. This can be done in the install.php file or in the model_setting_event table.

Common event triggers:

Event TriggerDescription
catalog/controller/*/beforeBefore any catalog controller executes
catalog/controller/*/afterAfter any catalog controller executes
catalog/model/*/beforeBefore any catalog model executes
catalog/model/*/afterAfter any catalog model executes
catalog/view/*/beforeBefore a view is rendered
admin/controller/*/beforeBefore any admin controller executes

Step 9: Package Your Extension

OpenCart 4 extensions are packed in a ZIP archive with a specific structure. The archive must contain the extension/ folder and cannot be zipped from a parent directory.

Packaging steps:

  1. Ensure your extension files are in the correct directory structure under extension/{vendor}/{extension_name}/
  2. Zip the contents of the extension folder-not the folder itself
  3. The resulting ZIP file should have extension/ as the top‑level directory
  4. Upload via Extensions > Installer in the admin panel

Important: Although OCMOD extensions still require the .ocmod.zip extension in some contexts, this naming convention is a remnant of OpenCart 3 and does not indicate active OCMOD functionality in all versions. For 4.1.x and newer, the installer handles both .zip and .ocmod.zip files.

Testing Your Extension

Unit Testing

Test individual components (controllers, models) in isolation. While OpenCart does not include a built‑in testing framework, you can use PHPUnit for custom tests.

Integration Testing

Test how your extension interacts with OpenCart’s core and other extensions. Verify:

  • Installation and uninstallation work correctly
  • Events fire as expected
  • No conflicts with other extensions

User Testing

Gather feedback from real users to identify usability issues and improve the user experience.

Performance Testing

Ensure your extension does not degrade store performance. Monitor:

  • Page load times with the extension enabled and disabled
  • Database query counts
  • Memory usage

Deploying Your Extension

Packaging for Distribution

Package your extension as a ZIP archive with the correct structure. Include:

  • All PHP, Twig, and language files
  • Installation scripts
  • Documentation (README, installation guide)

Documentation

Provide comprehensive documentation covering:

  • Installation instructions
  • Configuration steps
  • Troubleshooting tips
  • Changelog

Marketplace Submission

To distribute your extension via the OpenCart Marketplace, follow the submission guidelines on the OpenCart website. Ensure your extension meets the marketplace’s quality and security standards.

Maintaining Your Extension

Bug Fixes

Address user-reported issues promptly. Regular updates build trust with your users.

Compatibility Updates

Stay informed about OpenCart releases. Test your extension against new versions and release updates as needed. OpenCart 4.x continues to evolve-new features like Tasks and restored OCMOD functionality mean extension developers need to keep current.

User Support

Provide a clear support channel (email, forum, or ticketing system) and respond to inquiries promptly.

Best Practices for OpenCart 4 Extension Development

PracticeWhy It Matters
Follow OpenCart’s coding standardsEnsures compatibility and maintainability
Use the event system where possibleMore maintainable and less prone to conflicts than file modifications
Validate and sanitise all user inputPrevents security vulnerabilities
Use the self‑contained extension directoryCleaner structure, easier to version and maintain
Test on multiple PHP versionsOpenCart 4 runs on PHP 8.0+; ensure compatibility
Write clear documentationReduces support requests and improves user satisfaction
Use namespaces correctlyFollow the Opencart\Admin\Controller\Extension\{Vendor}\... pattern

Key Takeaways

  1. OpenCart 4 uses a self‑contained extension directory under /extension/{vendor}/, replacing the scattered file placement of OpenCart 3.
  2. OCMOD was restored in OpenCart 4.1.0.0 after being removed in early 4.0.x releases. For OpenCart 4.1.x and newer, both the event system and OCMOD are available.
  3. The event system remains the primary extension mechanism for hooking into core functionality without modifying core files.
  4. OpenCart 4.2 introduced Tasks-background processes for operations that do not require immediate feedback.
  5. OpenCart 4 requires PHP 8.0+ and uses namespaced classes with an MVC‑A pattern.
  6. Extensions are packaged as ZIP archives and installed via the admin panel’s Extensions > Installer.
  7. Regular maintenance-bug fixes, compatibility updates, and user support-is essential for a successful extension.

Conclusion

OpenCart 4 represents a significant evolution of the platform. The move to a self‑contained extension directory, the restoration of OCMOD, the introduction of Tasks, and the continued reliance on the event system give developers a flexible and powerful toolkit for extending the platform.

For new extensions, the event system should be your first choice. It is cleaner, more maintainable, and less likely to cause conflicts than file‑based modifications. If you are targeting OpenCart 4.1.x or newer, you have the additional option of using OCMOD for modifications that events cannot cover.

Careful planning, thorough testing, and ongoing maintenance are the keys to a successful extension. With OpenCart 4’s modern architecture and 2026’s current features, the possibilities for extension development are greater than ever.

References

Need help building an OpenCart 4 extension? Playful Sparkle has been engineering digital products since 2004, offering Web Development, App Development, and eCommerce solutions including OpenCart. Our team can help you design, develop, and maintain high‑quality OpenCart extensions. Contact us to discuss your project.

Was this helpful - Post
Zsolt Oroszlány

Zsolt Oroszlány

Founder & Chief Creative Officer of Playful Sparkle since 2004, combining business leadership, digital strategy, design, and software engineering to help organizations build effective digital solutions. Regularly publishes insights on web development, SEO, design, and emerging technologies.