Apex trigger anatomy
So far, we know that a trigger is defined by the following:
- An object type
- One or more events (before, after)
- A DML action (insert, update, delete, and undelete; upsert is just a short way to say do an insert or an update if the record already exists)
This is more or less the code involved in a trigger’s definition:
1. trigger OpportunityTrigger on Opportunity (before insert, before update,
2. before delete, after insert, after update,
3. after delete, after undelete) {
4. //code goes here…
5. }
All possible event combinations are referenced:
- Before events support insert, update, and delete operations.
- After events support insert, update, delete, and undelete operations.
If you want to refer to the specific event or operation, you would go with the Trigger keyword like this:
1. trigger OpportunityTrigger on Opportunity (before insert, before
2. update, before delete, after insert, after update, after delete,
after undelete) {
3. if(Trigger.isBefore){
4.
5. if(Trigger.isInsert || Trigger.isUpdate){
6. //before logic goes here…
7. }
8.
9. if(Trigger.isUpdate){
10. //before logic goes here…
11. }
12. }else if(Trigger.isAfter){
13. if(Trigger.isUpdate || Trigger.isInsert){
14. //after logic goes here…
15. }
16. }
17. }
As an experienced admin, I bet you get what it’s all about: it’s just a simple algorithm with a bunch of if statements that checks whether we are in a before or after event and, within each event, checks for a specific DML operation (the double slash indicates a comment, code that is never executed but is used to clarify what’s happening, and is a language feature that’s available in formulas and validation rules as well). When the trigger is fired (as we’ve seen in the order of execution list of automated actions), all the trigger’s code is executed, and it is important to define which lines of code may make sense for the before insert event but not for the after update event, and vice versa.
The before event
Where is the record that is being saved?
The Trigger keyword comes in handy as well and gives us access to current record values (and even to old ones):
1. trigger OpportunityTrigger on Opportunity (before insert, before
2. update, before delete, after insert, after update,
3. after delete, after undelete) {
4.
5. //current record (supposing only one opportunity can
be saved at once)
6. Opportunity currentOpp = Trigger.new[0];
7.
8. //treating before and after events separately
9. if(Trigger.isBefore){
10.
11. //following logic 0runs in before insert and update
12. if(Trigger.isInsert || Trigger.isUpdate){
13.
14. //error if opportunity has a negative amount
15. if(currentOpp.Amount <= 0){
16. //the addError() method is used to break the save
process
17. //and is shown to the current user on the page layout
18. currentOpp.addError(‘Invalid negative amount on
opportunity.’);
19. }
20. }
21.
22. //folowing login runs only for before update
23. if(Trigger.isUpdate){
24.
25. //gets the old values for an opportunity
26. Opportunity oldOpp = Trigger.old[0];
27.
28. //error if opportunity amount is discounted of more than
50%
29. Double newAmount = currentOpp.Amount;
30. Double oldAmount = oldOpp.Amount;
31.
32. if(newAmount > 0 && oldAmount > 0
33. && newAmount < (oldAmount * 0.5) ){
34. currentOpp.addError(‘Discount policies
forbit discounts ‘
35. + ‘higher than 50%. Please review the deal. ‘
36. + newAmount + ‘ vs ‘+oldAmount);
37. }
38. }
39. }else if(Trigger.isAfter){
40. if(Trigger.isUpdate || Trigger.isInsert){
41. //after logic goes here…
42. }
43. }
44. }
We have covered only the before event.
What’s happening?
Line 1 creates a new variable. A variable is just a temporary place where you can store a piece of data in Apex. It can store complex types such as Salesforce objects or simple types such as a string, an integer, or a date, for example.
Our first variable has the opportunity type, and it will contain the current opportunity record (supposing only one record is in the context of current trigger execution) that is taken from the Trigger.new property.