Iniziare a utilizzare i trigger Apex
Obiettivi di apprendimento
- Scrivere un trigger per un oggetto Salesforce.
- Utilizzare le variabili di contesto dei trigger.
- Chiamare un metodo di una classe da un trigger.
- Utilizzare il metodo
addError()
della classe sObject in un trigger per limitare le operazioni di salvataggio.
Prima di iniziare
I trigger Apex sono utili, divertenti e stimolanti. Questo modulo ti aiuta a iniziare a usarli, ma fa anche riferimento ad altre funzioni di Salesforce per mostrarti le potenzialità dei trigger Apex. Per trarre il massimo profitto da questo modulo, ti consigliamo di completare prima questi altri moduli:
Scrivere trigger Apex
Sintassi dei trigger
trigger
. Seguono poi il nome del trigger, l'oggetto Salesforce a cui il trigger è associato e le condizioni in cui viene eseguito. La sintassi dei trigger ha il seguente aspetto:trigger TriggerName on ObjectName (trigger_events) { code_block }
before insert
before update
before delete
after insert
after update
after delete
after undelete
Esempio di trigger
- Nella Developer Console, fai clic su File | New (Nuovo) | Apex Trigger (Trigger Apex).
- Inserisci
HelloWorldTrigger
come nome del trigger, quindi seleziona Account come sObject. Fai clic su Submit (Invia). - Sostituisci il codice predefinito con il seguente.
trigger HelloWorldTrigger on Account (before insert) { System.debug('Hello World!'); }
- Per salvare, premi Ctrl+S.
- Per testare il trigger, crea un account.
- Fai clic su Debug | Open Execute Anonymous Window (Apri finestra di esecuzione anonima).
- Nella nuova finestra, aggiungi questa riga, quindi fai clic su Execute (Esegui).
Account a = new Account(Name='Test Trigger'); insert a;
- Nel registro di debug, trova l'istruzione
Hello World!
. Il registro mostra inoltre che il trigger è stato eseguito.
Tipi di trigger
Esistono due tipi di trigger.
- I trigger before, utilizzati per aggiornare o convalidare i valori dei record prima che vengano salvati nel database.
- I trigger after, utilizzati per accedere ai valori dei campi impostati dal sistema (come il campo
Id
o il campoLastModifiedDate
di un record) e per effettuare modifiche in altri record. I record che innescano l'esecuzione del trigger after sono di sola lettura.
Utilizzare le variabili di contesto
Per accedere ai record che hanno determinato l'attivazione del trigger, occorre utilizzare le variabili di contesto. Ad esempio, Trigger.new
contiene tutti i record inseriti tramite trigger di inserimento o di aggiornamento. Trigger.old
fornisce la versione precedente degli sObject prima che venissero aggiornati dai trigger di aggiornamento, oppure un elenco di sObject eliminati dai trigger di eliminazione. L'esecuzione dei trigger può essere innescata quando viene inserito un record o quando vengono inseriti più record in blocco tramite l'API o Apex. Pertanto, le variabili di contesto, come Trigger.new
, possono contenere un solo record oppure più record. È possibile eseguire un'iterazione su Trigger.new
per ottenere ciascun sObject singolarmente.
Questo esempio è una versione modificata del trigger di esempio HelloWorldTrigger
. Esegue un'iterazione su ciascun account tramite un loop for e aggiorna il campo Description
(Descrizione) per ciascuno di essi.
trigger HelloWorldTrigger on Account (before insert) { for(Account a : Trigger.new) { a.Description = 'New description'; } }
Esistono altre variabili di contesto che restituiscono un valore booleano per indicare se l'esecuzione di un trigger è stata innescata da un aggiornamento o da un altro evento. Queste variabili sono utili quando un trigger combina più eventi. Ad esempio:
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 } }
La seguente tabella fornisce un elenco completo di tutte le variabili di contesto disponibili per i trigger.
Variabile | Utilizzo |
---|---|
isExecuting |
Restituisce true se il contesto corrente del codice Apex è un trigger e non una pagina Visualforce, un servizio web o una chiamata API executeanonymous() . |
isInsert |
Restituisce true se l'esecuzione del trigger è stata innescata da un'operazione di inserimento tramite l'interfaccia utente di Salesforce, Apex o l'API. |
isUpdate |
Restituisce true se l'esecuzione del trigger è stata innescata da un'operazione di aggiornamento tramite l'interfaccia utente di Salesforce, Apex o l'API. |
isDelete |
Restituisce true se l'esecuzione del trigger è stata innescata da un'operazione di eliminazione tramite l'interfaccia utente di Salesforce, Apex o l'API. |
isBefore |
Restituisce true se l'esecuzione del trigger è stata innescata prima del salvataggio di qualsiasi record. |
isAfter |
Restituisce true se l'esecuzione del trigger è stata innescata dopo il salvataggio di tutti i record. |
isUndelete |
Restituisce true se l'esecuzione del trigger è stata innescata dopo che un record è stato recuperato dal Cestino. Tale recupero può avvenire dopo un'operazione di annullamento dell'eliminazione tramite l'interfaccia utente di Salesforce, Apex o l'API. |
new |
Restituisce un elenco delle nuove versioni dei record sObject. Questo elenco di sObject è disponibile solo nei trigger |
newMap |
Una mappatura degli ID alle nuove versioni dei record sObject. Questa mappatura è disponibile solo nei trigger |
old |
Restituisce un elenco delle versioni precedenti dei record sObject. Questo elenco di sObject è disponibile solo nei trigger |
oldMap |
Una mappatura degli ID alle versioni precedenti dei record sObject. Questa mappatura è disponibile solo nei trigger |
operationType |
Restituisce un valore enum di tipo System.TriggerOperation corrispondente all'operazione corrente. I valori possibili dell'enum |
size |
Il numero totale di record, sia precedenti che nuovi, associati alla chiamata di un trigger. |
Chiamare un metodo di una classe da un trigger
Puoi chiamare i metodi di utilità pubblici con un trigger. Chiamare metodi di altre classi consente il riutilizzo del codice, riduce le dimensioni dei trigger e migliora la manutenzione del codice Apex. Inoltre, consente di utilizzare la programmazione orientata a oggetti.
Il seguente esempio di trigger mostra come chiamare un metodo statico con un trigger. Se l'esecuzione del trigger è stata innescata a causa di un evento di inserimento, l'esempio chiama il metodo statico sendMail()
della classe EmailManager
. Questo metodo di utilità invia un'email al destinatario specificato e contiene il numero di record dei referenti inseriti.
- Nella Developer Console, fai clic su File | New (Nuovo) | Apex Class (Classe Apex).
- Inserisci
EmailManager
e fai clic su OK. - Sostituisci il corpo predefinito della classe con l'esempio della classe
EmailManager
riportato qui sotto.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; } }
- Nella Developer Console, fai clic su File | New (Nuovo) | Apex Trigger (Trigger Apex).
- Inserisci
ExampleTrigger
come nome del trigger, quindi seleziona Contact (Referente) come sObject. Fai clic su Submit (Invia). - Sostituisci il codice predefinito con quello riportato di seguito, quindi modifica il testo del segnaposto dell'indirizzo email in
sendMail()
con il tuo indirizzo email.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 } }
- Per salvare, premi Ctrl+S.
- Per testare il trigger, crea un referente.
- Fai clic su Debug | Open Execute Anonymous Window (Apri finestra di esecuzione anonima).
- Nella nuova finestra, aggiungi questa riga, quindi fai clic su Execute (Esegui).
Contact c = new Contact(LastName='Test Contact'); insert c;
- Nel registro di debug, controlla che il trigger sia stato eseguito. Verso la fine del registro, trova il messaggio di debug scritto dal metodo di utilità:
DEBUG|Email sent successfully
(DEBUG| Messaggio email inviato correttamente) - Ora controlla di aver ricevuto un'email con il testo
1 contact(s) were inserted
(Referenti inseriti: 1).
Con il nuovo trigger attivo, ricevi un'email ogni volta che aggiungi uno o più referenti!
Aggiungere record correlati
I trigger vengono spesso utilizzati per l'accesso e la gestione dei record correlati ai record del contesto del trigger, ovvero i record che hanno causato l'attivazione del trigger.
Questo trigger aggiunge un'opportunità correlata per ciascun account nuovo o aggiornato se non è già stata associata un'opportunità all'account. Il trigger esegue innanzitutto una query SOQL per ottenere tutte le opportunità controllate dagli account su cui è stata innescata l'esecuzione del trigger. Successivamente, il trigger esegue un'iterazione sull'elenco di sObject in Trigger.new
per ottenere ciascun sObject Account. Se l'account non ha alcun sObject per le opportunità correlate, il loop for ne crea uno. Se il trigger ha creato nuove opportunità, l'istruzione finale le inserisce.
- Aggiungi il seguente trigger usando la Developer Console (segui i passaggi dell'esempio
HelloWorldTrigger
, ma usaAddRelatedRecord
come nome del trigger).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; } }
- Per testare il trigger, crea un account nell'interfaccia utente Salesforce e chiamalo
Apples & Oranges
(Mele e arance). - Individua la nuova opportunità nell'elenco correlato Opportunities (Opportunità) della pagina dell'account. Il trigger ha aggiunto questa opportunità automaticamente!
Utilizzare le eccezioni nei trigger
A volte è necessario aggiungere delle restrizioni su alcune operazioni di database, ad esempio impedire il salvataggio dei record quando si verificano determinate condizioni. Per impedire il salvataggio dei record in un trigger, chiama il metodo addError()
sull'sObject in questione. Il metodo addError()
genera un errore irreversibile all'interno di un trigger. Il messaggio di errore viene visualizzato nell'interfaccia utente e viene registrato.
Il trigger riportato di seguito impedisce l'eliminazione di un account se questo contiene delle opportunità correlate. Per impostazione predefinita, l'eliminazione di un account provoca la cancellazione a cascata di tutti i suoi record correlati. Questo trigger impedisce l'eliminazione a cascata delle opportunità. Prova questo trigger tu stesso! Se hai eseguito l'esempio precedente, la tua organizzazione ha un account chiamato Apples & Oranges
(Mele e arance) con un'opportunità correlata. In questo esempio viene utilizzato quell'account di esempio.
- Utilizzando la Developer Console, aggiungi il seguente trigger.
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.'); } }
- Nell'interfaccia utente di Salesforce, vai alla pagina dell'account
Apples & Oranges
(Mele e arance) e fai clic su Delete (Elimina). - Nel popup di conferma, fai clic su OK.
Trova l'errore di convalida con il messaggio di errore personalizzatoCannot delete account with related opportunities
(Impossibile eliminare account con opportunità correlate). - Disattiva il trigger
AccountDeletion
. Se lasci questo trigger attivo, non potrai controllare le tue sfide.- In Setup (Imposta), cerca
Apex Triggers
(Trigger Apex). - Nella pagina Apex Triggers (Trigger Apex), fai clic su Edit (Modifica) accanto al trigger
AccountDeletion
. - Deseleziona Is Active (È attivo).
- Fai clic su Save (Salva).
- In Setup (Imposta), cerca
Trigger e callout
Apex permette di effettuare chiamate e di integrare il codice Apex con servizi web esterni. Le chiamate Apex ai servizi web esterni si chiamano callout. Ad esempio, è possibile effettuare un callout a un servizio di quotazioni azionarie per ottenere le quotazioni più recenti. Quando si effettua il callout da un trigger, questo deve essere effettuato in modo asincrono, in modo che l'esecuzione del processo del trigger non si blocchi in attesa della risposta del servizio esterno. Il callout asincrono viene effettuato all'interno di un processo eseguito in background e la risposta arriva quando il servizio esterno la restituisce.
Per effettuare il callout da un trigger, è necessario chiamare un metodo di classe che viene eseguito in modo asincrono. Un metodo di questo tipo si chiama metodo future e deve contenere l'annotazione @future(callout=true)
. Questa classe di esempio contiene il metodo future che effettua il callout.
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); } }
In questo esempio viene mostrato il trigger che chiama il metodo della classe per effettuare un callout in modo asincrono.
trigger CalloutTrigger on Account (before insert, before update) { CalloutClass.makeCallout(); }
Questa sezione fornisce solo una panoramica dei callout e non intende trattare i callout nel dettaglio. Per saperne di più, vedi Invoking Callouts Using Apex (Richiamare i callout con Apex) nella Guida per sviluppatori Apex.