Premiers pas avec les déclencheurs Apex
Objectifs de formation
- Écrire un déclencheur pour un objet Salesforce
- Utiliser des variables de contexte de déclencheur
- Appeler une méthode de classe depuis un déclencheur
- Utiliser la méthode de sObject
addError()
dans un déclencheur pour empêcher les opérations de sauvegarde
Avant de commencer
Les déclencheurs Apex sont utiles, amusants et vraiment super. Ce module vous aide à les découvrir, mais il fait également référence à d’autres fonctionnalités Salesforce pour vous montrer la puissance des déclencheurs Apex. Afin de tirer le meilleur parti de ce module, nous vous recommandons vivement de consulter d’abord ces modules :
Écriture de déclencheurs Apex
Syntaxe d'un déclencheur
trigger
. Il est suivi du nom du déclencheur, de l'objet Salesforce auquel le déclencheur est associé et des conditions de son déclenchement. La syntaxe d'un déclencheur est la suivante :trigger TriggerName on ObjectName (trigger_events) { code_block }
before insert
before update
before delete
after insert
after update
after delete
after undelete
Exemple de déclencheur
- Dans la Developer Console, cliquez sur Fichier (File) | New (Nouveau) | Apex Trigger (Déclencheur Apex).
- Saisissez le nom de déclencheur
HelloWorldTrigger
, puis sélectionnez Account (Compte) pour le sObject. Cliquez sur Submit (Soumettre). - Remplacez le code par défaut par :
trigger HelloWorldTrigger on Account (before insert) { System.debug('Hello World!'); }
- Pour enregistrer, appuyez sur Ctrl+S.
- Pour tester le déclencheur, créez un compte.
- Cliquez sur Debug (Débogage) | Open Execute Anonymous Window (Ouvrir une fenêtre d’exécution anonyme).
- Dans la nouvelle fenêtre, ajoutez l'élément suivant, puis cliquez sur Execute (Exécuter).
Account a = new Account(Name='Test Trigger'); insert a;
- Dans le journal de débogage, recherchez l'instruction
Hello World!
. Le journal indique également que le déclencheur a été exécuté.
Types de déclencheur
Il existe deux types de déclencheurs.
- Les Before triggers (déclencheurs before) sont utilisés pour mettre à jour ou valider des valeurs d’enregistrement avant de les enregistrer dans la base de données.
- Les After triggers (déclencheurs after) sont utilisés pour accéder aux valeurs de champ définies par le système (par exemple le champ
Id
ouLastModifiedDate
d’un enregistrement), et pour appliquer les modifications dans d’autres enregistrements. Les enregistrements qui activent le déclencheur after sont en lecture seule.
Utilisation de variables de contexte
Pour accéder aux enregistrements qui activent le déclencheur, utilisez des variables de contexte. Par exemple, Trigger.new
contient tous les enregistrements insérés dans des déclencheurs insert ou update. Trigger.old
fournit l’ancienne version des sObjects avant leur mise à jour dans des déclencheurs update, ou la liste de sObjects supprimés dans des déclencheurs delete. Les déclencheurs peuvent être activés lors de l'insertion d'un enregistrement ou de l'insertion en masse de nombreux enregistrements via l'API ou Apex. Par conséquent, des variables de contexte (telles que Trigger.new
) peuvent contenir un seul ou plusieurs enregistrements. Vous pouvez itérer sur Trigger.new
pour obtenir chaque sObject individuel.
Cet exemple est une version modifiée de l'exemple de déclencheur HelloWorldTrigger
. Il itère sur chaque compte d’une boucle for et met à jour le champ Description
de chaque compte.
trigger HelloWorldTrigger on Account (before insert) { for(Account a : Trigger.new) { a.Description = 'New description'; } }
D'autres variables de contexte renvoient une valeur booléenne pour indiquer si le déclencheur a été activé suite à une mise à jour ou à un autre événement. Ces variables sont utiles lorsqu'un déclencheur combine plusieurs événements. Par exemple :
trigger ContextExampleTrigger on Account (before insert, after insert, after delete) { if (Trigger.isInsert) { if (Trigger.isBefore) { // Process before insert } else if (Trigger.isAfter) { // Process after insert } } else if (Trigger.isDelete) { // Process after delete } }
Le tableau ci-dessous présente la liste complète des variables de contexte disponibles pour les déclencheurs.
Variable | Utilisation |
---|---|
isExecuting |
Renvoie true si le contexte actuel du code Apex est un déclencheur, pas une page Visualforce, un service Web ni un appel API executeanonymous() . |
isInsert |
Renvoie true si le déclencheur a été activé suite à une opération d'insertion, à partir de l'interface utilisateur de Salesforce, Apex ou l'API. |
isUpdate |
Renvoie true si le déclencheur a été activé suite à une opération de mise à jour, à partir de l'interface utilisateur de Salesforce, Apex ou l'API. |
isDelete |
Renvoie true si le déclencheur a été activé suite à une opération de suppression, à partir de l'interface utilisateur de Salesforce, Apex ou l'API. |
isBefore |
Renvoie true si le déclencheur a été activé avant la sauvegarde des enregistrements. |
isAfter |
Renvoie true si le déclencheur a été activé après la sauvegarde de tous les enregistrements. |
isUndelete |
Renvoie true si le déclencheur a été activé après la récupération d’un enregistrement dans la corbeille. Cette récupération peut avoir lieu après une opération d’annulation de suppression dans l’interface utilisateur de Salesforce, d’Apex ou de l’API. |
new |
Renvoie la liste des nouvelles versions des enregistrements sObject. Cette liste de sObjects est disponible uniquement dans des déclencheurs |
newMap |
Un mappage des ID des nouvelles versions des enregistrements sObject. Ce mappage est disponible uniquement dans des déclencheurs |
old |
Renvoie la liste des anciennes versions des enregistrements sObject. Cette liste de sObjects est disponible uniquement dans des déclencheurs |
oldMap |
Un mappage des ID des anciennes versions des enregistrements sObject. Ce mappage est disponible uniquement dans des déclencheurs |
operationType |
Renvoie une énumération de type System.TriggerOperation correspondant à l’opération en cours. Les valeurs possibles de l’énumération |
size |
Le nombre total d'enregistrements dans une invocation de déclencheur, aussi bien anciens que nouveaux. |
Appel d'une méthode de classe à partir d'un déclencheur
Vous pouvez appeler des méthodes utilitaires à partir d'un déclencheur. L'appel de méthodes d'autres classes permet de réutiliser le code, de diminuer la taille de vos déclencheurs et d'améliorer la maintenance de votre code Apex. Il permet également d'utiliser une programmation orientée objet.
L'exemple de déclencheur ci-dessous montre comment appeler une méthode statique à partir d'un déclencheur. Si le déclencheur a été activé suite à un événement d'insertion, l'exemple appelle la méthode statique sendMail()
dans la classe EmailManager
. Cette méthode utilitaire envoie un e-mail au destinataire spécifié et contient le nombre d'enregistrements de contact insérés.
- Dans la Developer Console, cliquez sur File (Fichier) | New (Nouveau) | Apex Class (Classe Apex).
- Saisissez
EmailManager
, puis cliquez sur OK. - Remplacez le corps de classe par défaut par l’exemple de classe
EmailManager
ci-dessous.public class EmailManager { // Public method public static void sendMail(String address, String subject, String body) { // Create an email message object Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); String[] toAddresses = new String[] {address}; mail.setToAddresses(toAddresses); mail.setSubject(subject); mail.setPlainTextBody(body); // Pass this email message to the built-in sendEmail method // of the Messaging class Messaging.SendEmailResult[] results = Messaging.sendEmail( new Messaging.SingleEmailMessage[] { mail }); // Call a helper method to inspect the returned results inspectResults(results); } // Helper method private static Boolean inspectResults(Messaging.SendEmailResult[] results) { Boolean sendResult = true; // sendEmail returns an array of result objects. // Iterate through the list to inspect results. // In this class, the methods send only one email, // so we should have only one result. for (Messaging.SendEmailResult res : results) { if (res.isSuccess()) { System.debug('Email sent successfully'); } else { sendResult = false; System.debug('The following errors occurred: ' + res.getErrors()); } } return sendResult; } }
- Dans la Developer Console, cliquez sur Fichier (File) | New (Nouveau) | Apex Trigger (Déclencheur Apex).
- Saisissez le nom de déclencheur
ExampleTrigger
, puis sélectionnez Contact pour sObject. Cliquez sur Submit (Soumettre). - Remplacez le code par défaut par le code ci-dessous, puis remplacez le texte de l’espace réservé dans
sendMail()
par votre adresse e-mail.trigger ExampleTrigger on Contact (after insert, after delete) { if (Trigger.isInsert) { Integer recordCount = Trigger.new.size(); // Call a utility method from another class EmailManager.sendMail('Your email address', 'Trailhead Trigger Tutorial', recordCount + ' contact(s) were inserted.'); } else if (Trigger.isDelete) { // Process after delete } }
- Pour enregistrer, appuyez sur Ctrl+S.
- Pour tester le déclencheur, créez un contact.
- Cliquez sur Debug (Débogage) | Open Execute Anonymous Window (Ouvrir une fenêtre d’exécution anonyme).
- Dans la nouvelle fenêtre, ajoutez l'élément suivant, puis cliquez sur Execute (Exécuter).
Contact c = new Contact(LastName='Test Contact'); insert c;
- Dans le journal de débogage, assurez-vous que le déclencheur a été activé. Le message écrit par la méthode utilitaire est également indiqué à la fin du journal :
DEBUG|Email sent successfully
- Vérifiez maintenant si vous avez reçu un e-mail avec le corps de texte
1 contact(s) were inserted
.
Une fois votre nouveau déclencheur en place, vous recevez un e-mail chaque fois que vous ajoutez un ou plusieurs contacts !
Ajout d'enregistrements associés
Les déclencheurs sont souvent utilisés pour accéder à et gérer des enregistrements associés aux enregistrements dans le contexte du déclencheur (enregistrements qui ont entraîné l'activation du déclencheur).
Ce déclencheur ajoute une opportunité associée à chaque compte nouveau ou mis à jour si aucune opportunité ne lui est déjà associée. Le déclencheur exécute d'abord une requête SOQL pour récupérer les opportunités enfants des comptes dans lesquels il a été activé. Le déclencheur itère ensuite sur la liste de sObjects dans Trigger.new
pour obtenir chaque sObject de compte. Si en compte n'a aucun sObject d'opportunité associé, la boucle for en crée un. Si le déclencheur a créé des opportunités, l'instruction finale les insère.
- Ajoutez le déclencheur suivant à l’aide de la Developer Console (suivez les étapes de l’exemple
HelloWorldTrigger
, mais utilisez le nom de déclencheurAddRelatedRecord
).trigger AddRelatedRecord on Account(after insert, after update) { List<Opportunity> oppList = new List<Opportunity>(); // Get the related opportunities for the accounts in this trigger Map<Id,Account> acctsWithOpps = new Map<Id,Account>( [SELECT Id,(SELECT Id FROM Opportunities) FROM Account WHERE Id IN :Trigger.new]); // Add an opportunity for each account if it doesn't already have one. // Iterate through each account. for(Account a : Trigger.new) { System.debug('acctsWithOpps.get(a.Id).Opportunities.size()=' + acctsWithOpps.get(a.Id).Opportunities.size()); // Check if the account already has a related opportunity. if (acctsWithOpps.get(a.Id).Opportunities.size() == 0) { // If it doesn't, add a default opportunity oppList.add(new Opportunity(Name=a.Name + ' Opportunity', StageName='Prospecting', CloseDate=System.today().addMonths(1), AccountId=a.Id)); } } if (oppList.size() > 0) { insert oppList; } }
- Pour tester le déclencheur, créez un compte dans l'interface utilisateur de Salesforce, puis nommez-le
Apples & Oranges
. - Dans la liste associée Opportunities (Opportunités) de la page du compte, recherchez la nouvelle opportunité. Le déclencheur a automatiquement ajouté cette opportunité !
Utilisation d'exceptions de déclencheur
Il est parfois utile de définir des restrictions sur certaines opérations de base de données, par exemple pour empêcher la sauvegarde d'enregistrements lorsque certaines conditions sont remplies. Pour empêcher la sauvegarde d'enregistrements dans un déclencheur, appelez la méthode addError()
sur le sObject en question. La méthode addError()
renvoie une erreur fatale dans un déclencheur. Le message d'erreur est affiché dans l'interface utilisateur et est consigné.
Le déclencheur ci-dessous empêche la suppression d'un compte s'il a des opportunités associées. Par défaut, la suppression d'un compte entraîne la suppression en cascade de tous ses enregistrements associés. Ce déclencheur empêche la suppression en cascade des opportunités. Essayez ce déclencheur ! Si vous avez exécuté l’exemple précédent, votre organisation a un compte appelé Apples & Oranges
avec une opportunité associée. Cet exemple utilise ce compte.
- Dans la Developer Console, ajoutez le déclencheur suivant :
trigger AccountDeletion on Account (before delete) { // Prevent the deletion of accounts if they have related opportunities. for (Account a : [SELECT Id FROM Account WHERE Id IN (SELECT AccountId FROM Opportunity) AND Id IN :Trigger.old]) { Trigger.oldMap.get(a.Id).addError( 'Cannot delete account with related opportunities.'); } }
- Dans l'interface utilisateur de Salesforce, accédez à la page du compte
Apples & Oranges
, puis cliquez sur Delete (Supprimer). - Dans l’écran contextuel de confirmation, cliquez sur OK.
Recherchez l’erreur de validation avec le message personnaliséCannot delete account with related opportunities
(Impossible de supprimer un compte avec des opportunités liées). - Désactivez le déclencheur
AccountDeletion
. Si vous laissez ce déclencheur actif, vous ne pouvez pas utiliser vos questions de vérification.- Dans Setup (Configuration), recherchez
Apex Triggers
(Déclencheurs Apex). - Dans la page Apex Triggers (Déclencheurs Apex), cliquez sur Edit (Modifier) en regard du déclencheur
AccountDeletion
. - Désélectionnez Is Active (Actif).
- Cliquez sur Save (Enregistrer).
- Dans Setup (Configuration), recherchez
Déclencheurs et appels externes
Apex permet de transmettre des appels et d'intégrer votre code Apex à des services Web externes. Les appels Apex à des services Web externes sont appelés des appels externes. Par exemple, vous pouvez émettre un appel externe à un service de cotation boursière pour obtenir les derniers cours. Lors de la transmission d’un appel externe à partir d’un déclencheur, l’appel doit être effectué de façon asynchrone pour que le processus de déclenchement ne vous empêche pas de travailler en attendant la réponse du service externe. L’appel asynchrone est émis dans un processus en arrière-plan et la réponse est reçue lorsque le service externe la renvoie.
Pour émettre un appel externe à partir d'un déclencheur, appelez une méthode de classe exécutée de façon asynchrone. Ce type de méthode est appelé méthode future et est annoté avec @future(callout=true)
. Cet exemple de classe contient d'une méthode future qui génère l'appel externe.
public class CalloutClass { @future(callout=true) public static void makeCallout() { HttpRequest request = new HttpRequest(); // Set the endpoint URL. String endpoint = 'http://yourHost/yourService'; request.setEndPoint(endpoint); // Set the HTTP verb to GET. request.setMethod('GET'); // Send the HTTP request and get the response. HttpResponse response = new HTTP().send(request); } }
Cet exemple montre le déclencheur qui appelle la méthode dans la classe pour émettre un appel externe asynchrone.
trigger CalloutTrigger on Account (before insert, before update) { CalloutClass.makeCallout(); }
Cette section présente une vue d'ensemble des appels externes, sans préciser de détail. Pour plus d’informations, reportez-vous à Invocation d’appels en utilisant Apex dans le Guide du développeur Apex.