This trigger framework bundles a single triggerHandler base class that you inherit within all of your trigger handlers. The base class includes context-specific methods that are automatically called when a trigger is executed.
The base class also provides a secondary role as a supervisor for Trigger execution. It acts like a watchdog, monitoring trigger activity and providing an API for controlling certain aspects of execution and control flow.
But the most important part of this framework is that it's minimal and simple to use.
To create a trigger handler, you simply need to create a class that inherits from triggerHandler.cls. Here is an example for creating an Account trigger handler.
public class accountTriggerHandler extends triggerHandler {
Now add logic to any of the trigger contexts by overriding them in the handler. Here is how we would add logic to a beforeUpdate
trigger.
public class accountTriggerHandler extends triggerHandler {
//override for beforeUpdate
public override void beforeUpdate() {
for (Account a : (List<Account>)Trigger.new) {
// do something
}
}
//add overrides for other contexts like afterInsert
}
Note: When referencing the Trigger statics within a class, SObjects are returned instead of SObject subclasses like Opportunity, Contact, etc. This means that you must cast each object when you reference them in your trigger handler. This can be done in the constructor.
public class accountTriggerHandler extends triggerHandler {
private Map<Id, Account> newAccountMap; //map of Account.Id -> Account
//constructor
public accountTriggerHandler() {
this.newAccountMap = (Map<Id, Account>)Trigger.newMap; //cast the Map from the the Trigger context variable Trigger.newMap, which is a map of Ids to the new versions of the sObject records
}
//Trigger.isAfter AND Trigger.isUpdate contexts
public override void afterUpdate() {
//
}
}
To use the trigger handler, simply construct an instance of it within the trigger and call the run()
method. Here is an example of the Account trigger.
trigger accountTrigger on Account (before insert, before update) {
new accountTriggerHandler().run();
}
Here are all of the methods that can be overriden. All of the context possibilities are supported.
beforeInsert()
//Trigger.isBefore AND Trigger.isInsert contextsbeforeUpdate()
//Trigger.isBefore AND Trigger.isUpdate contextsbeforeDelete()
//Trigger.isBefore AND Trigger.isDelete contextsafterInsert()
//Trigger.isAfter AND Trigger.isInsert contextsafterUpdate()
//Trigger.isAfter AND Trigger.isUpdate contextsafterDelete()
//Trigger.isAfter AND Trigger.isDelete contextsafterUndelete()
//Trigger.isAfter AND Trigger.isUndelete contexts
To prevent recursion, you can set a max loop count. If this max is exceeded, and exception will be thrown. A great use case is when you want to ensure that your trigger runs once and only once within a single execution. Example:
public class accountTriggerHandler extends triggerHandler {
//constructor
public accountTriggerHandler() {
this.setMaxLoopCount(1); //loop only once
}
//Trigger.isAfter AND Trigger.isUpdate contexts
public override void afterUpdate() {
List<Account> acts = [SELECT Id FROM Account WHERE Id IN :Trigger.newMap.keySet()];
update acts; //will throw exception after this update
}
}
Need to inform other trigger handlers to halt execution? Use the bypass API. Example:
public class opportunityTriggerHandler extends triggerHandler {
//Trigger.isAfter AND Trigger.isUpdate contexts
public override void afterUpdate() {
List<Opportunity> opps = [SELECT Id, AccountId FROM Opportunity WHERE Id IN :Trigger.newMap.keySet()];
Account acc = [SELECT Id, Name FROM Account WHERE Id = :opps.get(0).AccountId];
triggerHandler.bypass('accountTriggerHandler');
acc.Name = 'No Trigger';
update acc; //won't invoke the accountTriggerHandler
triggerHandler.clearBypass('accountTriggerHandler');
acc.Name = 'With Trigger';
update acc; //will invoke the accountTriggerHandler
}
}
The Trigger_Status__c Custom Setting provides the option of turning a trigger on or off without having to deploy any code. This is useful if you simply need to prevent the trigger from firing for testing or data loads and cannot easily utilize the Bypass API logic.
The Custom Setting records are created automatically. So there is no need to worry about adding records manually. To see the status of any trigger handler classes:
- Navigate to Setup > Develop > Custom Settings.
- Click the Manage link located on the left-hand side of the Custom Setting reading Trigger Status.
- Rows correspond to the Apex Class that is designated as the handler for a given trigger.
- Click Edit to turn on/off the handler (as needed).