14

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?

DigitCart
  • 2,980
  • 2
  • 18
  • 28
Adnan
  • 579
  • 1
  • 4
  • 11
  • 2
    Caution to anyone coming to this question: Do not use events! All triggers have been removed from opencart 2.2. I don't know what they will still be there in the near future... – redochka Apr 08 '16 at 18:14
  • 5
    It took a while for me to find out but the old triggers have not been removed in 2.2 but replaced by a generic system that acts on ALL calls to models (and controllers, and that go via the registry and loader). This is done is loader.php that intercepts all calls to model objects and fires a before and after trigger. The names of the events have been changed though: post.order.history.add now is catalog/model/checkout/order/addOrderHistory/after (named after the model and method that triggers it). More info: https://github.com/opencart/opencart/wiki/Events-(script-notifications)-2.2.x.x – fietserwin Sep 15 '16 at 13:02
  • Events were introduced in 2.0, *completely* changed in 2.3, and changed yet again in 3.0. Great concept, just not stable enough. – Scott C Wilson Jun 21 '17 at 18:23
  • 2
    @ScottCWilson One of the reasons I gave up with OC... :-) – shadyyx Jun 26 '17 at 15:38
  • What do you use now @shadyyx ? – Scott C Wilson Jun 26 '17 at 15:57
  • 1
    I worked with OC as side projects until I got older and realized I have no more time for side projects and want to spend time with family :-) So I am not using anything for now. But honestly if I were for another project, I would first reach out for OC (newest stable version) :-) – shadyyx Jun 26 '17 at 16:26

3 Answers3

15

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

Dmitriy Zhuk
  • 757
  • 1
  • 6
  • 9
  • 2
    Very clear and explanatory. Thank for your time! – LucianDex Oct 19 '21 at 09:27
  • Is there a list of available event triggers, because I am searching for one that does trigger when an order status is updated. I tried registering like this: $this->model_extension_event->addEvent('editOrderEvent','catalog/model/checkout/order/editOrder/after','extension/module/newpay/editOrderHandler'); but it does not work. However, I managed to make it work when an order is created with this one: $this->model_extension_event->addEvent('newOrderEvent','catalog/model/checkout/order/addOrder/after','extension/module/newpay/newOrderHandler'); but that's not what I'm looking for. OC v2.3 – martin petrov Aug 31 '22 at 14:16
  • there is no list really, its based on the available controllers and from there you create the event trigger. you basically need to follow a pattern. your trigger seems to look correct, but I assume you are relying on the result. editOrder doesn't return anything, while addOrder returns an order id. could this be your issue? – Dmitriy Zhuk Jan 03 '23 at 18:43
  • Worth mentioning that triggers for libraries are available only in Opencart 4.x – Taras Jul 06 '23 at 17:46
5

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).

shadyyx
  • 15,825
  • 6
  • 60
  • 95
5

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.

Scott C Wilson
  • 19,102
  • 10
  • 61
  • 83
raxbg
  • 79
  • 4
  • 3
    Links to external resources are encouraged, but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline. http://stackoverflow.com/help/how-to-answer – Eeji Dec 15 '14 at 21:59
  • Ok, the essentials are here. I am not going to spend 10 or more minutes copying content from the the linked page to here. – raxbg Dec 31 '14 at 18:17
  • See comment #2 in response to OP; this solution is no longer correct. – Scott C Wilson Jun 18 '17 at 20:01