Skip to main content

Iniziare a utilizzare i trigger Apex

Obiettivi di apprendimento

Al completamento di questa unità, sarai in grado di:
  • 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.
Nota

Nota

Stai seguendo la formazione in italiano? In questo badge, la convalida delle sfide pratiche di Trailhead funziona in inglese. Le traduzioni sono fornite tra parentesi come riferimento. Nel tuo Trailhead Playground, accertati di (1) selezionare Stati Uniti per le impostazioni internazionali, (2) impostare la lingua su Inglese e (3) copiare e incollare soltanto i valori in lingua inglese. Segui le istruzioni qui.

Visita il badge Trailhead nella tua lingua per scoprire come usufruire dell'esperienza di Trailhead in altre lingue.

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

I trigger Apex permettono di eseguire azioni personalizzate prima o dopo eventi che riguardano i record di Salesforce, ad esempio inserimenti, aggiornamenti o eliminazioni. Analogamente a quanto accade nei sistemi di database, Apex fornisce il supporto dei trigger per la gestione dei record.

Normalmente si utilizzano i trigger per eseguire operazioni basate su condizioni specifiche, per modificare record correlati o per limitare l'esecuzione di determinate operazioni. È possibile utilizzare i trigger per eseguire tutte le operazioni consentite in Apex, ivi compresa l'esecuzione di SOQL e DML o la chiamata di metodi Apex personalizzati.

I trigger possono essere usati per eseguire operazioni non eseguibili con gli strumenti "point-and-click" dell'interfaccia utente di Salesforce. Ad esempio, se vuoi convalidare il valore di un campo o aggiornare il campo di un record, usa i flussi e le regole di convalida. Usa i trigger Apex se le prestazioni e la scalabilità sono importanti, se la logica è troppo complessa per gli strumenti point-and-click o se esegui operazioni che prevedono un uso intensivo della CPU.

I trigger possono essere definiti per gli oggetti standard di primo livello, ad esempio Account o Referente, per gli oggetti personalizzati e per alcuni oggetti secondari standard. Per impostazione predefinita, i trigger sono attivi sin dal momento della loro creazione. Salesforce esegue automaticamente i trigger attivi quando si verificano gli eventi di database specificati.

Sintassi dei trigger

La sintassi per la definizione dei trigger è diversa da quella utilizzata per definire le classi. La definizione di un trigger inizia con la parola chiave 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
}
Per eseguire un trigger prima o dopo le operazioni di inserimento, aggiornamento, eliminazione e annullamento dell'eliminazione, occorre specificare più eventi trigger in un elenco separato da virgole. Gli eventi specificabili sono:
  • before insert
  • before update
  • before delete
  • after insert
  • after update
  • after delete
  • after undelete

Esempio di trigger

Questo semplice trigger viene eseguito prima dell'inserimento di un account e scrive un messaggio nel registro di debug.
  1. Nella Developer Console, fai clic su File | New (Nuovo) | Apex Trigger (Trigger Apex).
  2. Inserisci HelloWorldTrigger come nome del trigger, quindi seleziona Account come sObject. Fai clic su Submit (Invia).
  3. Sostituisci il codice predefinito con il seguente.

    trigger HelloWorldTrigger on Account (before insert) {
    	System.debug('Hello World!');
    }
  4. Per salvare, premi Ctrl+S.
  5. Per testare il trigger, crea un account.
    1. Fai clic su Debug | Open Execute Anonymous Window (Apri finestra di esecuzione anonima).
    2. Nella nuova finestra, aggiungi questa riga, quindi fai clic su Execute (Esegui).

      Account a = new Account(Name='Test Trigger');
      insert a;
  6. 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 campo LastModifiedDate 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';
    }   
}
Nota

Il sistema salva i record che hanno attivato il trigger before al termine dell'esecuzione del trigger. È possibile modificare i record del trigger senza chiamare esplicitamente un'operazione DML di inserimento o aggiornamento. Se si eseguono istruzioni DML su questi record, si verifica un errore.

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 insert, update e undelete e i record sono modificabili solo nei trigger before.

newMap Una mappatura degli ID alle nuove versioni dei record sObject.

Questa mappatura è disponibile solo nei trigger before update, after insert, after update e after undelete.

old Restituisce un elenco delle versioni precedenti dei record sObject.

Questo elenco di sObject è disponibile solo nei trigger update e delete.

oldMap Una mappatura degli ID alle versioni precedenti dei record sObject.

Questa mappatura è disponibile solo nei trigger update e delete.

operationType Restituisce un valore enum di tipo System.TriggerOperation corrispondente all'operazione corrente.

I valori possibili dell'enum System.TriggerOperation sono: BEFORE_INSERT, BEFORE_UPDATE, BEFORE_DELETE, AFTER_INSERT, AFTER_UPDATE, AFTER_DELETE, and AFTER_UNDELETE. Se intendi variare la logica di programmazione in base a diversi tipi di trigger, prendi in considerazione l'utilizzo dell'istruzione switch con diverse permutazioni di stati di esecuzione enumerati univoci dei trigger.

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.

  1. Nella Developer Console, fai clic su File | New (Nuovo) | Apex Class (Classe Apex).
  2. Inserisci EmailManager e fai clic su OK.
  3. 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;
        }
    }
  4. Nella Developer Console, fai clic su File | New (Nuovo) | Apex Trigger (Trigger Apex).
  5. Inserisci ExampleTrigger come nome del trigger, quindi seleziona Contact (Referente) come sObject. Fai clic su Submit (Invia).
  6. 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
        }
    }
  7. Per salvare, premi Ctrl+S.
  8. Per testare il trigger, crea un referente.
    1. Fai clic su Debug | Open Execute Anonymous Window (Apri finestra di esecuzione anonima).
    2. Nella nuova finestra, aggiungi questa riga, quindi fai clic su Execute (Esegui).
      Contact c = new Contact(LastName='Test Contact');
      insert c;
  9. 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)
  10. 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!

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.

  1. Aggiungi il seguente trigger usando la Developer Console (segui i passaggi dell'esempio HelloWorldTrigger, ma usa AddRelatedRecord 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;
        }
    }
  2. Per testare il trigger, crea un account nell'interfaccia utente Salesforce e chiamalo Apples & Oranges (Mele e arance).
  3. Individua la nuova opportunità nell'elenco correlato Opportunities (Opportunità) della pagina dell'account. Il trigger ha aggiunto questa opportunità automaticamente!
Nota

Il trigger che hai aggiunto esegue l'iterazione su tutti i record che fanno parte del contesto del trigger: il loop for esegue l'iterazione su Trigger.new. Tuttavia, il loop di questo trigger potrebbe essere più efficiente. In realtà non abbiamo bisogno di accedere a tutti gli account associati al contesto di questo trigger, ma solo a un sottoinsieme: gli account che non contengono opportunità. Nella prossima unità vedremo come rendere questo trigger più efficiente. Nell'unità Schemi di progettazione in blocco dei trigger, imparerai a modificare la query SOQL per ottenere solo gli account che non contengono opportunità. Dopodiché, imparerai a eseguire l'iterazione solo su quei record.

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.

  1. 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.');
        }
    }
  2. Nell'interfaccia utente di Salesforce, vai alla pagina dell'account Apples & Oranges (Mele e arance) e fai clic su Delete (Elimina).
  3. Nel popup di conferma, fai clic su OK.

    Trova l'errore di convalida con il messaggio di errore personalizzato Cannot delete account with related opportunities (Impossibile eliminare account con opportunità correlate).

  4. Disattiva il trigger AccountDeletion. Se lasci questo trigger attivo, non potrai controllare le tue sfide.
    1. In Setup (Imposta), cerca Apex Triggers (Trigger Apex).
    2. Nella pagina Apex Triggers (Trigger Apex), fai clic su Edit (Modifica) accanto al trigger AccountDeletion.
    3. Deseleziona Is Active (È attivo).
    4. Fai clic su Save (Salva).
Nota
La chiamata ad addError() in un trigger causa il rollback dell'intero insieme di operazioni, tranne nel caso in cui il DML in blocco venga chiamato con riuscita parziale.
  • Se l'esecuzione del trigger è stata innescata da una chiamata DML in blocco nell'API di Lightning Platform, il motore di runtime esclude i record con errori. Il motore di runtime tenta quindi un salvataggio parziale dei record che non hanno generato errori.
  • Se il trigger è stato eseguito a partire da un'istruzione DML in Apex, qualsiasi errore comporta il rollback dell'intera operazione. Tuttavia, il motore di runtime elabora comunque ogni record dell'operazione per compilare un elenco completo di errori.

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.

Nota

L'esempio utilizza un l'URL di un endpoint ipotetico a scopo puramente illustrativo. Non è possibile eseguire questo esempio se non si modifica l'endpoint utilizzando un URL valido e non si aggiunge un sito remoto in Salesforce per l'endpoint.

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.

Continua a imparare gratuitamente!
Registra un account per continuare.
Cosa troverai?
  • Ottieni consigli personalizzati per i tuoi obiettivi di carriera
  • Metti in pratica le tue competenze con sfide pratiche e quiz
  • Monitora e condividi i tuoi progressi con i datori di lavoro
  • Accedi a risorse di tutoraggio e opportunità di carriera