How can we use opencart events?

Adnan picture Adnan · Oct 17, 2014 · Viewed 11.5k times · Source

I have searched a lot about opencart triggers but didn't find a proper example. In opencart 2.0 there are triggers on which developer can hook function and perform something just like wordpress action and filters i guess. For example in

catalog/model/checkout/order.php

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

Can someone help me to hook my function on the above trigger?

Answer

Dmitriy Zhuk picture Dmitriy Zhuk · Mar 11, 2019

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