Writing Opencart extensions with events

In this post you will understand how to write module/extension with events.
Since Opencart 3.0.3.5 the ocmod file modifications doesn't modfy the templates
and therefore if you have some changes in your extension, which need to modify
the opencart files, they wont be applied. So the only way to add menu or extra
javascript or css is through events.

There are benefits and limitations about the events. The most import important
change is that you will not change the file, but you can modify the data passed
to the view. Events are more difficult to learn, but then you don't rely on some
strings in a file which could change with the new version and therefore your
extension or module willl stop working.

The event has 3 important parts:

1. Event identifier
2. The trgger
3. And finally the code which would be executed when the event is fired

Let's start with a sample module which would add on admin seciton a menu on the
left side menu and also add a javascript file in the header of the site.

As you may know every extension/module should have an "upload" directory which
should contain the code.

Therefore we need 2 files - controller and translation file (otherwise our new
module would have title "heading_title" which is not very useful in real life).

upload/admin/controller/extension/module/example_event_extension.php
upload/admin/language/en-gb/extension/module/example_event_extension.php

In the language file there should be at least 1 row which would be the title of
the module. So the contents of the file would look like

$_['heading_title'] = 'Example Event Extension';

Now the most important part - the controller.


class ControllerExtensionModuleExampleEventExtension extends Controller {
public function install()
{
$this->load->model('setting/event');
$this->model_setting_event->addEvent(
'example_event_extension_menu',
'admin/view/common/column_left/before',
'extension/module/example_event_extension/addMenu'
);
$this->model_setting_event->addEvent(
'example_event_extension_script',
'admin/view/common/header/before',
'extension/module/example_event_extension/addScript'
);
}
public function uninstall()
{
$this->load->model('setting/event');
$this->model_setting_event->deleteEventByCode(
'example_event_extension_menu'
);
$this->model_setting_event->deleteEventByCode(
'example_event_extension_script'
);
}
public function addMenu($eventRoute, &$data)
{
$data['menus'][] = [
'id' => 'some-menu-example',
'icon' => 'fa fa-shopping-cart fa-fw',
'name' => 'Example extension',
'href' => '#test',
''
];
}
public function addScript($eventRoute, &$data)
{
$data['scripts'][] = 'view/javascript/example.js';
}
}

So, in the controller who has class name ControllerExtensionModuleExampleEventExtension
and extends Controller there are 2 main functions:

install() and uninstall()

They would be responsible to register and unregister the event on the site.

In install as you can see we load the model setting/event and then use the function


$this->model_setting_event->addEvent($event_id, $trigger, $code);

$event_id - this is the identifier of the event which you could see in
Extensions>Events table where you could enable or disable or event remove from
the site. The naming convention should be lowercase with underscores, but I
doubt this would matter. In my example file my identifier is "example_event_extension_menu"

$trigger - this is when the event will "fire". It's important to know that the
trigger has 2 places where it can be executed "before" and "after".

$code - this point to a file and function which would execute the code (for this
a bit later)

Those triggers could be applied on controller, model, view, language etc. To see
all possible options, I would recommend to take a look on the following file:

system/storage/modification/system/engine/loader.php in your opencart instance.

So in our example our triggers is are:


admin/view/common/column_left/before
admin/view/common/header/before

First one would be responsible to add the new menu, and the second one would add
the javascript.

As you can see the trigger follows the path of the file which need to be "tampered".
In our case the first one is "admin/view/common/column_left" and the trigger would
be executed before it's rendered. If we add /after at the end, then we would receive
the rendered html of the view.

The same way you could have trigger in admin/controller/common/header/after which
could modify the controller and it's data.

In our case in before event we have the variable $data which is passed from
the controller to the view.

And finally we need the code which would be executed when the event is fired. (the $code part)

In our simplified example the code point to the same controller file like so:


extension/module/example_event_extension/addMenu
extension/module/example_event_extension/addScript

Now that's the tricky part, at least it took me a while to inderstand the logic, but
as you can see the code executed doesn't have 'admin/controller' prefix and the
path should follow the file name path rather than the class name, but that's how it is.

In our example because our $code is in the same file the part
"extension/module/example_event_extension" means the path to the file without the
admin and controller and finally at the end you have the function which would be executed.

Now if you reached this point, you could dump the $data variable which is passed as a
second argument of the function and you will see all the nodes which you pass to the view
from the controller and therefore in the function addMenu we add one final node
and in addScript we add the script to the scripts node.

And that's it. You could modify the $data variable and therefore add our new content.

Of course there is a uninstall() function which simply just remove the event rows from
the events table and therefore they are uninstalled.

If you have the similar structure, once installed, you should have a new module under
the

Extensions/Extensions/Modules section which you could install/uninstall. Further you
could add a details page in the edit module section where you could add some extra
configurations for your module.

You could find the full example here

Let me know if you have some thoughts in the comments below.

Nik Chankov
Nik Chankov
a.k.a. nchankov

Nik started creating opencart extensions since 2011. And has more than 20 years experience in Software development.