How can we use opencart events?

Important Note: this answer applies to OC >2.0.x.x and <2.2.x.x.

The problem here is a wrong word being used (and searched for) - the right one you should be searching for is event, and from it derived event listener and trigger event (unfortunately, hadn't luck when trying to search for those either and the documentation for 2.0 is still missing).

Now I believe the whole background is much more understandable, especially if you have some knowledge about events from other frameworks (maybe jQuery?) but here is just a quick guide how to work with events (in OC 2.0):

  • first we need to register an event listener, like this:

    $this->event->register('post.order.history.add', 'checkout/order/send_email');

  • on certain places an event is triggered, e.g.

    $this->event->trigger('pre.order.history.add', $order_id);

    and

    $this->event->trigger('post.order.history.add', $order_id);

  • if the event (identified by it's name post.order.history.add) listener was registered it will be invoked on trigger

For more information or to figure it out on your own you may have a look into system/engine/event.php (there is nothing more to work with right now).


I think this question should be updated since the update to OpenCart v2.3.x OC events have changed dramatically.

Before they resembled the Wordpress approach. You would have a list of predefined events with before and after trigger.

Starting from version 2.3.x and then changing a little bit in version 3.x, OC events became more dynamic, where the triggers are dynamically defined based on the path structure of the files.

What are the benefits of using events.

  1. Much less conflicts. With modification systems you are altering the code itself, where with events you are modifying the passed around data which is an array, object or a string.
  2. You can easily update your event logic. Since the code for events sits in a simple controller file, you can update the file for the events to get updated, unlike with OCmod where you need to remove the old Ocmod file and upload a new one.
  3. Much more control over your data. Because you are altering the data and not the code, you have more power over it.
  4. Much cleaner code. Well, because you are just writing php. No xml and stuff.
  5. Lets you upgrade your OpenCart my easier. OpenCart can change the code, but will not radically change the data. So in most cases your events will work just fine.

Of course, there are some disadvantages:

  1. Hard to learn and understand.
  2. Events are only available for controllers, models, views, library and config. If you want to edit something other then that, you will have to use OCmod.

I would recommend using Events where possible, and fallback to OCmod where events have no access to.

How do OpenCart Events work

When a controller (model, view, library or language) is loaded via the loader class like so:

$this->load->controller('common/header');

the method controller() in file system/engine/loader.php does the following

  1. first triggers the event before for the route common/header
$trigger = $route;

$result = $this->registry->get('event')->trigger('controller/' . $trigger . '/before', array(&$route, &$data));
  1. then runs the code for loading the controller
$action = new Action($route);
$output = $action->execute($this->registry, array(&$data));
  1. and finally triggers the event after for the route common/header
$result = $this->registry->get('event')->trigger('controller/' . $trigger . '/after', array(&$route, &$data, &$output));

this is very much the same for model, language, library and config.

What is an OpenCart event Trigger

OpenCart matches the currently loading controller route (like the one we loaded above) common/header (same goes for model, view, language, and config) with the registered events in the system.

You will add a trigger when you register your event.

For Controller common/home in catalog before it loads

The trigger will look like this: catalog/controller/common/home/before

For Model sale/order for method getOrder in catalog after it loads

The trigger will look like this: catalog/model/sale/order/getOrder/after

Important, in model you will always set the trigger for the method, unlike the controller, where there is a default method index which is often dropped

For View catalog/product_form.twig in admin on after

The trigger will look like this: admin/view/catalog/product_form/after

remember that when adding an event to a view after, you will be modifying the &$output veriable which by now is not a twig file, but a fully compiled HTML. So there are no twig tags in the code any longer.

the best way to modify your view if by using the PHP Simple HTML Dom Parser

How to register an event

There are three options to register an OpenCart Event.

  1. register via the model $this->model_setting_event->addEvent(); (recommended)
  2. register via the config file in system/config/catalog edit $_['action_event']
  3. register via the admin with the help of d_event_manager module.

I will show you how to add via the model since that is the recommended way.

  1. Add code for registering an event on update of Status.

in your file admin/controller/extension/module/my_module.php


$this->load->model('setting/event');
$this->model_setting_event->deleteEventByCode('my_module');
if($this->request->post['module_my_module_status']){
    $this->model_setting_event->addEvent('my_module', 
    'admin/view/catalog/product_form/before', 
    'extension/module/my_module/view_catalog_product_form_before');
}

notice that I first remove all the events and then check if the status is true and add the events. this way I can be sure that no old or unexpected events get added.

  1. Remove all events on uninstall
public function uninstall(){
    $this->load->model('setting/event');
    $this->model_setting_event->deleteEventByCode('my_module');
}

It is good practice to remove all events after your module if it is being uninstalled.

Where do I write OpenCart Event functions?

Right now you know that there are Events which have triggers. But what do the triggers actually do?

They just load the controller of the event and pass the data by reference.

This is why:

  1. You will always add your event logic into a controller in admin or catalog folder. (even if you are setting an event for a config or library)
  2. with an event function you can modify the $route and $data on before event and $route and $output on after event

Here is an example of a Event function in file admin/controller/extension/module/my_module.php

public function view_catalog_product_form_before(&$route, &$data){
    if($data && isset($this->request->get['product_id'])){
        $product_id = $this->request->get['product_id'];
        $this->load->model('extension/module/my_module');

        $product_info = $this->model_extension_module_my_module->getMoreProductInfo($product_id);

        if($product_info){
            //here I am modifying the $data and it will pass on to the view with this new data because it was passed to this function by referance. 
            $data['more_info'] = $product_info;
        }
    }
    //there is no result returned in Event functions. 
    //if you do return a result, you will override the default result that can cause unexpected consequences. best to avoid it. 
}

Enjoy! If you have any questions, send us a message at https://dreamvention.com


Important Note: this answer applies to OC >2.0.x.x and <2.2.x.x.

The event system works like this:

  1. OpenCart loads a list with all registered event handlers from the database. This happens at the end of the index.php file.
  2. Then the event handlers are registered in the $event object, which is an instance of the Event class (system/engine/event.php)
  3. Then the $event->trigger() method is being called from different parts of the system. The trigger method accepts an event name as a parameter and all event handlers registered for this event name are being executed.

You can use the $event object to register event handlers or trigger events at runtime, but do this in special cases only. Have in mind that you will most likely need to access the $event object through $this->event and not $event (depending on where you need it).

Most often, you will need to register your event handlers in the db table only once using the extension/event model . You can do this in your install() method of your admin controller, for example. Something like this:

public function install() {
    $this->load->model('extension/event');
    $this->model_extension_event->addEvent('mymodule', 'pre.admin.store.delete', 'module/mymodule/on_store_delete');
    $this->model_extension_event->addEvent('mymodule', 'post.customer.add', 'module/mymodule/on_customer_add');
}

The event handlers are the third parameter of the addEvent() method and they are in the form of a standard route.

You can find more about the event system here: http://isenselabs.com/posts/opencart2-event-system-tutorial. It is a tutorial explaining how the event system works and has simple examples which show you how to make use of it in your extensions.