Apex - Guide rapide

Qu'est-ce qu'Apex?

Apex est un langage propriétaire développé par Salesforce.com. Selon la définition officielle, Apex est un langage de programmation orienté objet fortement typé qui permet aux développeurs d'exécuter les instructions de contrôle de flux et de transaction sur le serveur de la plateforme Force.com en conjonction avec des appels à l'API Force.com.

Il a une syntaxe de type Java et agit comme des procédures stockées dans une base de données. Il permet aux développeurs d'ajouter une logique métier à la plupart des événements système, y compris les clics sur les boutons, les mises à jour d'enregistrement associées et Visualforcepages.Apexle code peut être initié par des requêtes de service Web et par des déclencheurs sur des objets. Apex est inclus dans Performance Edition, Unlimited Edition, Enterprise Edition et Developer Edition.

Caractéristiques d'Apex en tant que langage

Parlons maintenant des fonctionnalités d'Apex en tant que langage -

Intégré

Apex a intégré la prise en charge des opérations DML telles que INSERT, UPDATE, DELETE ainsi que la gestion des exceptions DML. Il prend en charge la gestion des requêtes SOQL et SOSL en ligne qui renvoie l'ensemble des enregistrements sObject. Nous étudierons en détail sObject, SOQL, SOSL dans les prochains chapitres.

Java comme la syntaxe et facile à utiliser

Apex est facile à utiliser car il utilise la syntaxe comme Java. Par exemple, déclaration de variable, syntaxe de boucle et instructions conditionnelles.

Fortement intégré aux données

Apex est axé sur les données et conçu pour exécuter plusieurs requêtes et instructions DML ensemble. Il émet plusieurs déclarations de transaction sur la base de données.

Fortement typé

Apex est un langage fortement typé. Il utilise une référence directe à des objets de schéma comme sObject et toute référence non valide échoue rapidement si elle est supprimée ou si son type de données est incorrect.

Environnement multi-locataire

Apex s'exécute dans un environnement mutualisé. Par conséquent, le moteur d'exécution Apex est conçu pour se protéger étroitement contre le code emballé, l'empêchant de monopoliser les ressources partagées. Tout code qui enfreint les limites échoue avec des messages d'erreur faciles à comprendre.

Mises à niveau automatiquement

Apex est mis à niveau dans le cadre des versions de Salesforce. Nous n'avons pas besoin de le mettre à jour manuellement.

Test facile

Apex fournit une prise en charge intégrée pour la création et l'exécution de tests unitaires, y compris les résultats de test qui indiquent la quantité de code couverte et les parties de votre code qui peuvent être plus efficaces.

Quand les développeurs devraient-ils choisir Apex?

Apex doit être utilisé lorsque nous ne sommes pas en mesure d'implémenter la fonctionnalité métier complexe à l'aide des fonctionnalités prêtes à l'emploi préconfigurées et existantes. Vous trouverez ci-dessous les cas dans lesquels nous devons utiliser apex sur la configuration Salesforce.

Applications Apex

Nous pouvons utiliser Apex quand nous le voulons -

  • Créez des services Web avec l'intégration d'autres systèmes.

  • Créez des services de messagerie pour l'explosion d'e-mails ou la configuration d'e-mails.

  • Effectuez une validation complexe sur plusieurs objets en même temps et une implémentation de validation personnalisée.

  • Créez des processus métier complexes qui ne sont pas pris en charge par les fonctionnalités ou les flux de flux de travail existants.

  • Créez une logique transactionnelle personnalisée (logique qui se produit sur toute la transaction, pas seulement avec un seul enregistrement ou objet), comme en utilisant les méthodes Database pour mettre à jour les enregistrements.

  • Exécutez une certaine logique lorsqu'un enregistrement est modifié ou modifiez l'enregistrement de l'objet associé lorsqu'un événement a provoqué le déclenchement du déclencheur.

Structure de travail d'Apex

Comme indiqué dans le diagramme ci-dessous (Référence: Documentation du développeur Salesforce), Apex s'exécute entièrement à la demande Force.com Platform

Flux d'actions

Il y a deux séquences d'actions lorsque le développeur enregistre le code et lorsqu'un utilisateur final effectue une action qui appelle le code Apex comme indiqué ci-dessous -

Action du développeur

Lorsqu'un développeur écrit et enregistre du code Apex sur la plate-forme, le serveur d'applications de la plate-forme compile d'abord le code dans un ensemble d'instructions pouvant être compris par l'interpréteur d'exécution Apex, puis enregistre ces instructions sous forme de métadonnées.

Action de l'utilisateur final

Lorsqu'un utilisateur final déclenche l'exécution d'Apex, en cliquant sur un bouton ou en accédant à une page Visualforce, le serveur d'applications de la plateforme récupère les instructions compilées à partir des métadonnées et les envoie via l'interpréteur d'exécution avant de renvoyer le résultat. L'utilisateur final n'observe aucune différence de temps d'exécution par rapport à la demande de plate-forme d'application standard.

Comme Apex est le langage propriétaire de Salesforce.com, il ne prend pas en charge certaines fonctionnalités, contrairement à un langage de programmation général. Voici quelques fonctionnalités que Apex ne prend pas en charge -

  • Il ne peut pas afficher les éléments dans l'interface utilisateur.

  • Vous ne pouvez pas modifier la fonctionnalité fournie par SFDC standard et il n'est pas non plus possible d'empêcher l'exécution de la fonctionnalité standard.

  • La création de plusieurs threads n'est pas non plus possible car nous pouvons le faire dans d'autres langues.

Comprendre la syntaxe Apex

Le code Apex contient généralement de nombreuses choses que nous connaissons peut-être dans d'autres langages de programmation.

Déclaration de variable

En tant que langage fortement typé, vous devez déclarer chaque variable avec un type de données dans Apex. Comme le montre le code ci-dessous (capture d'écran ci-dessous), lstAcc est déclaré avec le type de données Liste des comptes.

Requête SOQL

Cela sera utilisé pour récupérer les données de la base de données Salesforce. La requête illustrée dans la capture d'écran ci-dessous récupère les données de l'objet Account.

Déclaration de boucle

Cette instruction de boucle est utilisée pour itérer sur une liste ou pour itérer sur un morceau de code pendant un nombre de fois spécifié. Dans le code montré dans la capture d'écran ci-dessous, l'itération sera identique au nombre d'enregistrements que nous avons.

Déclaration de contrôle de flux

L'instruction If est utilisée pour le contrôle de flux dans ce code. Sur la base de certaines conditions, il est décidé de passer à l'exécution ou d'arrêter l'exécution du morceau de code particulier. Par exemple, dans le code ci-dessous, il vérifie si la liste est vide ou contient des enregistrements.

Déclaration DML

Effectue les opérations d'insertion, de mise à jour, d'upsert et de suppression d'enregistrements sur les enregistrements de la base de données. Par exemple, le code ci-dessous aide à mettre à jour les comptes avec une nouvelle valeur de champ.

Voici un exemple de l'apparence d'un extrait de code Apex. Nous allons étudier plus en détail tous ces concepts de programmation Apex dans ce tutoriel.

Dans ce chapitre, nous allons comprendre l'environnement de notre développement Salesforce Apex. On suppose que vous avez déjà configuré une édition Salesforce pour le développement Apex.

Vous pouvez développer le code Apex dans l'édition Sandbox ou Developer de Salesforce. Une organisation Sandbox est une copie de votre organisation dans laquelle vous pouvez écrire du code et le tester sans prendre le risque de modifier les données ou de perturber le fonctionnement normal. Conformément à la pratique industrielle standard, vous devez développer le code dans Sandbox, puis le déployer dans l'environnement de production.

Pour ce didacticiel, nous utiliserons l'édition Developer de Salesforce. Dans l'édition Developer, vous n'aurez pas la possibilité de créer une organisation Sandbox. Les fonctionnalités Sandbox sont disponibles dans d'autres éditions de Salesforce.

Outils de développement de code Apex

Dans toutes les éditions, nous pouvons utiliser l'un des trois outils suivants pour développer le code -

  • Console développeur Force.com
  • IDE Force.com
  • Éditeur de code dans l'interface utilisateur de Salesforce

Note − Nous utiliserons la Developer Console tout au long de notre didacticiel pour l'exécution de code, car elle est simple et conviviale pour l'apprentissage.

Console développeur Force.com

La Developer Console est un environnement de développement intégré avec un ensemble d'outils que vous pouvez utiliser pour créer, déboguer et tester des applications dans votre organisation Salesforce.

Suivez ces étapes pour ouvrir la Developer Console -

Step 1 − Accédez à Nom → Developer Console

Step 2 − Cliquez sur "Developer Console" et une fenêtre apparaîtra comme dans la capture d'écran suivante.

Voici quelques opérations qui peuvent être effectuées à l'aide de la Developer Console.

  • Writing and compiling code −Vous pouvez écrire le code à l'aide de l'éditeur de code source. Lorsque vous enregistrez un déclencheur ou une classe, le code est automatiquement compilé. Toutes les erreurs de compilation seront signalées.

  • Debugging −Vous pouvez écrire le code à l'aide de l'éditeur de code source. Lorsque vous enregistrez un déclencheur ou une classe, le code est automatiquement compilé. Toutes les erreurs de compilation seront signalées.

  • Testing − Vous pouvez afficher les journaux de débogage et définir des points de contrôle qui facilitent le débogage.

  • Checking performance −Vous pouvez exécuter des tests de classes de test spécifiques ou de toutes les classes de votre organisation, et vous pouvez afficher les résultats des tests. En outre, vous pouvez inspecter la couverture du code.

  • SOQL queries − Vous pouvez inspecter les journaux de débogage pour localiser les goulots d'étranglement des performances.

  • Color coding and autocomplete − L'éditeur de code source utilise un jeu de couleurs pour une lisibilité plus facile des éléments de code et fournit une saisie semi-automatique pour les noms de classes et de méthodes.

Exécution du code dans la Developer Console

Tous les extraits de code mentionnés dans ce didacticiel doivent être exécutés dans la console développeur. Suivez ces étapes pour exécuter les étapes dans la Developer Console.

Step 1 - Connectez-vous à Salesforce.com en utilisant login.salesforce.com. Copiez les extraits de code mentionnés dans le didacticiel. Pour l'instant, nous allons utiliser l'exemple de code suivant.

String myString = 'MyString';
System.debug('Value of String Variable'+myString);

Step 2 - Pour ouvrir la Developer Console, cliquez sur Nom → Developer Console, puis sur Execute Anonymous comme indiqué ci-dessous.

Step 3 - Dans cette étape, une fenêtre apparaîtra et vous pourrez y coller le code.

Step 4 - Quand on clique sur Execute, les journaux de débogage s'ouvriront. Une fois que le journal apparaît dans la fenêtre comme indiqué ci-dessous, cliquez sur l'enregistrement du journal.

Tapez ensuite 'USER' dans la fenêtre comme indiqué ci-dessous et l'instruction de sortie apparaîtra dans la fenêtre de débogage. Cette instruction 'USER' est utilisée pour filtrer la sortie.

Donc, fondamentalement, vous suivrez toutes les étapes mentionnées ci-dessus pour exécuter un extrait de code dans ce didacticiel.

Exemple de développement d'applications d'entreprise

Pour notre tutoriel, nous mettrons en œuvre l'application CRM pour une entreprise d'équipement et de traitement chimique. Cette société traite avec les fournisseurs et fournit des services. Nous élaborerons de petits extraits de code liés à cet exemple tout au long de notre didacticiel pour comprendre chaque concept en détail.

Pour exécuter le code de ce didacticiel, vous devrez créer deux objets: les objets Client et Facture. Si vous savez déjà comment créer ces objets dans Salesforce, vous pouvez ignorer les étapes ci-dessous. Sinon, vous pouvez suivre le guide étape par étape ci-dessous.

Création d'un objet client

Nous allons d'abord configurer l'objet Client.

Step 1- Allez dans Configuration, puis recherchez «Objet» comme indiqué ci-dessous. Cliquez ensuite sur le lien Objets comme indiqué ci-dessous.

Step 2 - Une fois la page objet ouverte, cliquez sur le bouton 'Create New Object'comme indiqué ci-dessous.

Step 3- Après avoir cliqué sur le bouton, la nouvelle page de création d'objet apparaîtra, puis entrez tous les détails de l'objet comme indiqué ci-dessous. Le nom de l'objet doit être Customer. Il vous suffit de saisir les informations dans le champ comme indiqué dans la capture d'écran ci-dessous et de conserver les autres éléments par défaut tels quels.

Entrez les informations puis cliquez sur le bouton 'Enregistrer' -

En suivant les étapes ci-dessus, nous avons créé avec succès l'objet Client.

Création des champs personnalisés pour l'objet client

Maintenant que nous avons configuré notre objet Client, nous allons créer un champ «Actif» et vous pourrez ensuite créer les autres champs en suivant des étapes similaires. Le nom et le nom de l'API du champ seront indiqués dans la capture d'écran.

Step 1- Nous allons créer un champ nommé «Actif» de type de données comme Case à cocher. Allez dans Configuration et cliquez dessus.

Step 2 - Recherchez «Objet» comme indiqué ci-dessous et cliquez dessus.

Step 3 - Cliquez sur l'objet 'Client'.

Step 4 - Une fois que vous avez cliqué sur le lien de l'objet Client et que la page de détail de l'objet apparaît, cliquez sur le bouton Nouveau.

Step 5 - Maintenant, sélectionnez le type de données comme Case à cocher et cliquez sur Suivant.

Step 6 - Entrez le nom du champ et l'étiquette comme indiqué ci-dessous.

Step 7 - Cliquez sur Visible puis sur Suivant.

Step 8 - Cliquez maintenant sur «Enregistrer».

En suivant les étapes ci-dessus, notre champ personnalisé «Actif» est créé. Vous devez suivre toutes les étapes de création de champs personnalisés ci-dessus pour les champs restants. Ceci est la vue finale de l'objet client une fois que tous les champs sont créés -

Création d'un objet de facture

Step 1 - Allez dans Configuration et recherchez «Objet», puis cliquez sur le lien Objets comme indiqué ci-dessous.

Step 2 - Une fois la page d'objet ouverte, cliquez sur le bouton «Créer un nouvel objet» comme indiqué ci-dessous.

Step 3- Après avoir cliqué sur le bouton, la nouvelle page de création d'objet apparaîtra comme indiqué dans la capture d'écran ci-dessous. Vous devez entrer les détails ici. Le nom de l'objet doit être Facture. Ceci est similaire à la façon dont nous avons créé l'objet Customer plus tôt dans ce didacticiel.

Step 4 - Entrez les informations comme indiqué ci-dessous, puis cliquez sur le bouton «Enregistrer».

En suivant ces étapes, votre objet Facture sera créé.

Création des champs personnalisés pour l'objet Facture

Nous allons créer le champ Description sur l'objet Facture comme indiqué ci-dessous -

Step 1 - Allez dans Configuration et cliquez dessus.

Step 2 - Recherchez «Objet» comme indiqué ci-dessous et cliquez dessus.

Step 3 - Cliquez sur l'objet 'Facture'.

Et puis cliquez sur «Nouveau».

Step 4 - Sélectionnez le type de données comme Zone de texte, puis cliquez sur le bouton Suivant.

Step 5 - Saisissez les informations ci-dessous.

Step 6 - Cliquez sur Visible puis sur Suivant.

Step 7 - Cliquez sur Enregistrer.

De même, vous pouvez créer les autres champs sur l'objet Facture.

Par cela, nous avons créé les objets nécessaires à ce didacticiel. Nous apprendrons divers exemples dans les chapitres suivants basés sur ces objets.

Comprendre les types de données

Le langage Apex est fortement typé, de sorte que chaque variable dans Apex sera déclarée avec le type de données spécifique. Toutes les variables apex sont initialisées à null au départ. Il est toujours recommandé à un développeur de s'assurer que les valeurs appropriées sont attribuées aux variables. Sinon, de telles variables, lorsqu'elles sont utilisées, lèveront des exceptions de pointeur nul ou des exceptions non gérées.

Apex prend en charge les types de données suivants -

  • Primitive (Integer, Double, Long, Date, Datetime, String, ID ou Boolean)

  • Collections (listes, décors et cartes) (à traiter au chapitre 6)

  • sObject

  • Enums

  • Classes, objets et interfaces (à traiter dans les chapitres 11, 12 et 13)

Dans ce chapitre, nous examinerons tous les types de données primitifs, sObjects et Enums. Nous examinerons les collections, les classes, les objets et les interfaces dans les prochains chapitres, car ce sont des sujets clés à apprendre individuellement.

Types de données primitifs

Dans cette section, nous discuterons des types de données primitifs pris en charge par Apex.

Entier

Un nombre de 32 bits qui n'inclut aucun point décimal. La plage de valeurs pour cela commence de -2 147 483 648 et la valeur maximale est de 2 147 483 647.

Example

Nous voulons déclarer une variable qui stockera la quantité de barils à expédier à l'acheteur de l'usine de traitement chimique.

Integer barrelNumbers = 1000;
system.debug(' value of barrelNumbers variable: '+barrelNumbers);

le System.debug() function imprime la valeur de la variable afin que nous puissions l'utiliser pour déboguer ou pour savoir quelle valeur la variable détient actuellement.

Collez le code ci-dessus dans la console développeur et cliquez sur Exécuter. Une fois les journaux générés, la valeur de la variable "barrelNumbers" sera de 1000.

Booléen

Cette variable peut être vraie, fausse ou nulle. Plusieurs fois, ce type de variable peut être utilisé comme indicateur dans la programmation pour identifier si la condition particulière est définie ou non.

Example

Si la valeur booléenne shippingDispatched doit être définie sur true, elle peut être déclarée comme -

Boolean shipmentDispatched;
shipmentDispatched = true;
System.debug('Value of shipmentDispatched '+shipmentDispatched);

Date

Ce type de variable indique une date. Cela ne peut stocker que la date et non l'heure. Pour enregistrer la date avec l'heure, nous aurons besoin de la stocker dans la variable DateTime.

Example

Prenons l'exemple suivant pour comprendre le fonctionnement de la variable Date.

//ShipmentDate can be stored when shipment is dispatched.
Date ShipmentDate = date.today();
System.debug('ShipmentDate '+ShipmentDate);

Longue

Il s'agit d'un nombre 64 bits sans point décimal. Ceci est utilisé lorsque nous avons besoin d'une plage de valeurs plus large que celles fournies par Integer.

Example

Si les revenus de l'entreprise doivent être stockés, nous utiliserons le type de données Long.

Long companyRevenue = 21474838973344648L;
system.debug('companyRevenue'+companyRevenue);

Objet

Nous pouvons faire référence à tout type de données pris en charge dans Apex. Par exemple, la variable de classe peut être un objet de cette classe, et le type générique sObject est également un objet et un type d'objet spécifique similaire comme Account est également un objet.

Example

Prenons l'exemple suivant pour comprendre le fonctionnement de la variable bject.

Account objAccount = new Account (Name = 'Test Chemical');
system.debug('Account value'+objAccount);

Note - Vous pouvez également créer un objet de classe prédéfinie, comme indiqué ci-dessous -

//Class Name: MyApexClass
MyApexClass classObj = new MyApexClass();

C'est l'objet de classe qui sera utilisé comme variable de classe.

Chaîne

La chaîne est un ensemble de caractères entre guillemets simples. Il n'a pas de limite pour le nombre de caractères. Ici, la taille du tas sera utilisée pour déterminer le nombre de caractères. Cela met un frein au monopole des ressources par le programme Apex et garantit également qu'il ne devient pas trop grand.

Example

String companyName = 'Abc International';
System.debug('Value companyName variable'+companyName);

Temps

Cette variable est utilisée pour stocker l'heure particulière. Cette variable doit toujours être déclarée avec la méthode statique du système.

Goutte

Le Blob est une collection de données binaires stockées en tant qu'objet. Cela sera utilisé lorsque nous souhaitons stocker la pièce jointe dans Salesforce dans une variable. Ce type de données convertit les pièces jointes en un seul objet. Si le blob doit être converti en chaîne, nous pouvons utiliser les méthodes toString et valueOf pour le même.

sObjet

Il s'agit d'un type de données spécial dans Salesforce. Il est similaire à une table en SQL et contient des champs similaires aux colonnes en SQL. Il existe deux types de sObjects: standard et personnalisé.

Par exemple, Account est un sObject standard et tout autre objet défini par l'utilisateur (comme l'objet Customer que nous avons créé) est un sObject personnalisé.

Example

//Declaring an sObject variable of type Account
Account objAccount = new Account();

//Assignment of values to fields of sObjects
objAccount.Name = 'ABC Customer';
objAccount.Description = 'Test Account';
System.debug('objAccount variable value'+objAccount);

//Declaring an sObject for custom object APEX_Invoice_c
APEX_Customer_c objCustomer = new APEX_Customer_c();

//Assigning value to fields
objCustomer.APEX_Customer_Decscription_c = 'Test Customer';
System.debug('value objCustomer'+objCustomer);

Enum

Enum est un type de données abstrait qui stocke une valeur d'un ensemble fini d'identificateurs spécifiés. Vous pouvez utiliser le mot-clé Enum pour définir un Enum. Enum peut être utilisé comme tout autre type de données dans Salesforce.

Example

Vous pouvez déclarer les noms possibles de Chemical Compound en exécutant le code suivant -

//Declaring enum for Chemical Compounds
public enum Compounds {HCL, H2SO4, NACL, HG}
Compounds objC = Compounds.HCL;
System.debug('objC value: '+objC);

Java et Apex sont similaires à bien des égards. La déclaration de variable dans Java et Apex est également assez similaire. Nous allons discuter de quelques exemples pour comprendre comment déclarer des variables locales.

String productName = 'HCL';
Integer i = 0;
Set<string> setOfProducts = new Set<string>();
Map<id, string> mapOfProductIdToName = new Map<id, string>();

Notez que toutes les variables sont affectées avec la valeur null.

Declaring Variables

Vous pouvez déclarer les variables dans Apex comme String et Integer comme suit -

String strName = 'My String';  //String variable declaration
Integer myInteger = 1;         //Integer variable declaration
Boolean mtBoolean = true;      //Boolean variable declaration

Apex variables are Case-Insensitive

Cela signifie que le code donné ci-dessous générera une erreur puisque la variable «m» a été déclarée deux fois et que les deux seront traitées comme identiques.

Integer m = 100;
for (Integer i = 0; i<10; i++) {
   integer m = 1; //This statement will throw an error as m is being declared
   again
   System.debug('This code will throw error');
}

Scope of Variables

Une variable Apex est valide à partir du point où elle est déclarée dans le code. Il n'est donc pas permis de redéfinir la même variable à nouveau et dans le bloc de code. De plus, si vous déclarez une variable dans une méthode, la portée de cette variable sera limitée à cette méthode particulière uniquement. Cependant, les variables de classe sont accessibles dans toute la classe.

Example

//Declare variable Products
List<string> Products = new List<strings>();
Products.add('HCL');

//You cannot declare this variable in this code clock or sub code block again
//If you do so then it will throw the error as the previous variable in scope
//Below statement will throw error if declared in same code block
List<string> Products = new List<strings>();

La chaîne dans Apex, comme dans tout autre langage de programmation, est un ensemble de caractères sans limite de caractères.

Example

String companyName = 'Abc International';
System.debug('Value companyName variable'+companyName);

Méthodes de chaîne

La classe String dans Salesforce a de nombreuses méthodes. Nous examinerons certaines des méthodes de chaîne les plus importantes et les plus fréquemment utilisées dans ce chapitre.

contient

Cette méthode retournera true si la chaîne donnée contient la sous-chaîne mentionnée.

Syntax

public Boolean contains(String substring)

Example

String myProductName1 = 'HCL';
String myProductName2 = 'NAHCL';
Boolean result = myProductName2.contains(myProductName1);
System.debug('O/p will be true as it contains the String and Output is:'+result);

équivaut à

Cette méthode retournera true si la chaîne donnée et la chaîne passée dans la méthode ont la même séquence binaire de caractères et qu'elles ne sont pas nulles. Vous pouvez également comparer l'ID d'enregistrement SFDC en utilisant cette méthode. Cette méthode est sensible à la casse.

Syntax

public Boolean equals(Object string)

Example

String myString1 = 'MyString';
String myString2 = 'MyString';
Boolean result = myString2.equals(myString1);
System.debug('Value of Result will be true as they are same and Result is:'+result);

equalsIgnoreCase

Cette méthode retournera true si stringtoCompare a la même séquence de caractères que la chaîne donnée. Cependant, cette méthode n'est pas sensible à la casse.

Syntax

public Boolean equalsIgnoreCase(String stringtoCompare)

Example

Le code suivant retournera true car les caractères de chaîne et la séquence sont identiques, en ignorant le respect de la casse.

String myString1 = 'MySTRING';
String myString2 = 'MyString';
Boolean result = myString2.equalsIgnoreCase(myString1);
System.debug('Value of Result will be true as they are same and Result is:'+result);

retirer

Cette méthode supprime la chaîne fournie dans stringToRemove de la chaîne donnée. Cela est utile lorsque vous souhaitez supprimer certains caractères spécifiques de la chaîne et que vous ne connaissez pas l'index exact des caractères à supprimer. Cette méthode est sensible à la casse et ne fonctionnera pas si la même séquence de caractères se produit mais que la casse est différente.

Syntax

public String remove(String stringToRemove)

Example

String myString1 = 'This Is MyString Example';
String stringToRemove = 'MyString';
String result = myString1.remove(stringToRemove);
System.debug('Value of Result will be 'This Is Example' as we have removed the MyString 
   and Result is :'+result);

removeEndIgnoreCase

Cette méthode supprime la chaîne fournie dans stringToRemove de la chaîne donnée, mais uniquement si elle se produit à la fin. Cette méthode n'est pas sensible à la casse.

Syntax

public String removeEndIgnoreCase(String stringToRemove)

Example

String myString1 = 'This Is MyString EXAMPLE';
String stringToRemove = 'Example';
String result = myString1.removeEndIgnoreCase(stringToRemove);
System.debug('Value of Result will be 'This Is MyString' as we have removed the 'Example'
   and Result is :'+result);

commence avec

Cette méthode retournera true si la chaîne donnée commence par le préfixe fourni dans la méthode.

Syntax

public Boolean startsWith(String prefix)

Example

String myString1 = 'This Is MyString EXAMPLE';
String prefix = 'This';
Boolean result = myString1.startsWith(prefix);
System.debug(' This will return true as our String starts with string 'This' and the 
   Result is :'+result);

Les tableaux dans Apex sont fondamentalement les mêmes que les listes dans Apex. Il n'y a pas de distinction logique entre les tableaux et les listes car leur structure de données internes et leurs méthodes sont également identiques, mais la syntaxe des tableaux est peu traditionnelle comme Java.

Voici la représentation d'un tableau de produits -

Index 0 - HCL

Index 1 - H2SO4

Index 2 - NACL

Index 3 - H2O

Index 4 - N2

Index 5 - U296

Syntaxe

<String> [] arrayOfProducts = new List<String>();

Exemple

Supposons que nous devions stocker le nom de nos produits - nous pouvons utiliser le tableau où, nous stockerons les noms de produit comme indiqué ci-dessous. Vous pouvez accéder au produit particulier en spécifiant l'index.

//Defining array
String [] arrayOfProducts = new List<String>();

//Adding elements in Array
arrayOfProducts.add('HCL');
arrayOfProducts.add('H2SO4');
arrayOfProducts.add('NACL');
arrayOfProducts.add('H2O');
arrayOfProducts.add('N2');
arrayOfProducts.add('U296');

for (Integer i = 0; i<arrayOfProducts.size(); i++) {
   //This loop will print all the elements in array
   system.debug('Values In Array: '+arrayOfProducts[i]);
}

Accès à un élément de tableau à l'aide de l'index

Vous pouvez accéder à n'importe quel élément du tableau en utilisant l'index comme indiqué ci-dessous -

//Accessing the element in array
//We would access the element at Index 3
System.debug('Value at Index 3 is :'+arrayOfProducts[3]);

Comme dans tout autre langage de programmation, les constantes sont les variables qui ne changent pas de valeur une fois déclarées ou affectées d'une valeur.

Dans Apex, les constantes sont utilisées lorsque nous voulons définir des variables qui doivent avoir une valeur constante tout au long de l'exécution du programme. Les constantes Apex sont déclarées avec le mot-clé «final».

Exemple

Considérez un CustomerOperationClass classe et une variable constante regularCustomerDiscount à l'intérieur -

public class CustomerOperationClass {
   static final Double regularCustomerDiscount = 0.1;
   static Double finalPrice = 0;
   
   public static Double provideDiscount (Integer price) {
      //calculate the discount
      finalPrice = price - price * regularCustomerDiscount;
      return finalPrice;
   }
}

Pour voir la sortie de la classe ci-dessus, vous devez exécuter le code suivant dans la fenêtre anonyme de Developer Console -

Double finalPrice = CustomerOperationClass.provideDiscount(100);
System.debug('finalPrice '+finalPrice);

Les structures de prise de décision exigent que le programmeur spécifie une ou plusieurs conditions à évaluer ou à tester par le programme, ainsi qu'une ou plusieurs instructions à exécuter si la condition est jugée vraie, et éventuellement d'autres instructions à exécuter si le condition est considérée comme fausse.

Dans ce chapitre, nous étudierons la structure de base et avancée de la prise de décision et des déclarations conditionnelles dans Apex. La prise de décision est nécessaire pour contrôler le flux d'exécution lorsque certaines conditions sont remplies ou non. Voici la forme générale d'une structure de prise de décision typique trouvée dans la plupart des langages de programmation

Sr.No. Déclaration et description
1 if déclaration

Une instruction if consiste en une expression booléenne suivie d'une ou plusieurs instructions.

2 if ... instruction else

Une instruction if peut être suivie d'une option else instruction, qui s'exécute lorsque l'expression booléenne est fausse.

3 instruction if ... elseif ... else

Une instruction if peut être suivie d'une option else if...else instruction, qui est très utile pour tester diverses conditions en utilisant une instruction if ... else if unique.

4 instruction if imbriquée

Vous pouvez en utiliser un if or else if déclaration dans un autre if or else if déclaration (s).

Les boucles sont utilisées lorsqu'un morceau de code particulier doit être répété avec le nombre d'itérations souhaité. Apex prend en charge la boucle for traditionnelle standard ainsi que d'autres types avancés de boucles. Dans ce chapitre, nous discuterons en détail des boucles dans Apex.

Une instruction de boucle nous permet d'exécuter une instruction ou un groupe d'instructions plusieurs fois et suit le général à partir d'une instruction de boucle dans la plupart des langages de programmation -

Les tableaux suivants répertorient les différentes boucles qui gèrent les exigences de boucle dans le langage de programmation Apex. Cliquez sur les liens suivants pour vérifier leurs détails.

Sr.No. Type de boucle et description
1 pour boucle

Cette boucle exécute un ensemble d'instructions pour chaque élément d'un ensemble d'enregistrements.

2 SOQL pour boucle

Exécutez une séquence d'instructions directement sur l'ensemble retourné de la requête SOQL.

3 Boucle for de type Java

Exécutez une séquence d'instructions dans la syntaxe traditionnelle de type Java.

4 boucle while

Répète une instruction ou un groupe d'instructions tant qu'une condition donnée est vraie. Il teste la condition avant d'exécuter le corps de la boucle.

5 faire ... boucle while

Comme une instruction while, sauf qu'elle teste la condition à la fin du corps de la boucle.

Les collections est un type de variable qui peut stocker plusieurs nombres d'enregistrements. Par exemple, List peut stocker plusieurs enregistrements de l'objet Account. Voyons maintenant un aperçu détaillé de tous les types de collections.

Listes

La liste peut contenir n'importe quel nombre d'enregistrements de primitifs, de collections, de sObjects, définis par l'utilisateur et construits en type Apex. Il s'agit de l'un des types de collection les plus importants et il comporte également des méthodes système spécialement conçues pour être utilisées avec List. L'index de liste commence toujours par 0. Ceci est synonyme de tableau en Java. Une liste doit être déclarée avec le mot-clé «Liste».

Example

Ci-dessous se trouve la liste qui contient la liste d'un type de données primitif (chaîne), c'est-à-dire la liste des villes.

List<string> ListOfCities = new List<string>();
System.debug('Value Of ListOfCities'+ListOfCities);

La déclaration des valeurs initiales de list est facultative. Cependant, nous déclarerons ici les valeurs initiales. Voici un exemple qui montre la même chose.

List<string> ListOfStates = new List<string> {'NY', 'LA', 'LV'};
System.debug('Value ListOfStates'+ListOfStates);

Liste des comptes (sObject)

List<account> AccountToDelete = new List<account> (); //This will be null
System.debug('Value AccountToDelete'+AccountToDelete);

Nous pouvons également déclarer la liste imbriquée. Cela peut aller jusqu'à cinq niveaux. C'est ce qu'on appelle la liste multidimensionnelle.

C'est la liste des ensembles d'entiers.

List<List<Set<Integer>>> myNestedList = new List<List<Set<Integer>>>();
System.debug('value myNestedList'+myNestedList);

La liste peut contenir n'importe quel nombre d'enregistrements, mais il existe une limitation de la taille du tas pour éviter le problème de performances et monopoliser les ressources.

Méthodes pour les listes

Il existe des méthodes disponibles pour les listes que nous pouvons être utilisées lors de la programmation pour obtenir certaines fonctionnalités comme le calcul de la taille de la liste, l'ajout d'un élément, etc.

Voici quelques méthodes les plus fréquemment utilisées -

  • size()
  • add()
  • get()
  • clear()
  • set()

L'exemple suivant illustre l'utilisation de toutes ces méthodes

// Initialize the List
List<string> ListOfStatesMethod = new List<string>();

// This statement would give null as output in Debug logs
System.debug('Value of List'+ ListOfStatesMethod);

// Add element to the list using add method
ListOfStatesMethod.add('New York');
ListOfStatesMethod.add('Ohio');

// This statement would give New York and Ohio as output in Debug logs
System.debug('Value of List with new States'+ ListOfStatesMethod);

// Get the element at the index 0
String StateAtFirstPosition = ListOfStatesMethod.get(0);

// This statement would give New York as output in Debug log
System.debug('Value of List at First Position'+ StateAtFirstPosition);

// set the element at 1 position
ListOfStatesMethod.set(0, 'LA');

// This statement would give output in Debug log
System.debug('Value of List with element set at First Position' + ListOfStatesMethod[0]);

// Remove all the elements in List
ListOfStatesMethod.clear();

// This statement would give output in Debug log
System.debug('Value of List'+ ListOfStatesMethod);

Vous pouvez également utiliser la notation de tableau pour déclarer la liste, comme indiqué ci-dessous, mais ce n'est pas une pratique générale en programmation Apex -

String [] ListOfStates = new List<string>();

Ensembles

Un ensemble est un type de collection qui contient plusieurs nombres d'enregistrements uniques non ordonnés. Un ensemble ne peut pas avoir d'enregistrements en double. Comme les listes, les ensembles peuvent être imbriqués.

Example

Nous définirons l'ensemble des produits que l'entreprise vend.

Set<string> ProductSet = new Set<string>{'Phenol', 'Benzene', 'H2SO4'};
System.debug('Value of ProductSet'+ProductSet);

Méthodes pour les ensembles

Set prend en charge les méthodes que nous pouvons utiliser lors de la programmation comme indiqué ci-dessous (nous étendons l'exemple ci-dessus) -

// Adds an element to the set
// Define set if not defined previously
Set<string> ProductSet = new Set<string>{'Phenol', 'Benzene', 'H2SO4'};
ProductSet.add('HCL');
System.debug('Set with New Value '+ProductSet);

// Removes an element from set
ProductSet.remove('HCL');
System.debug('Set with removed value '+ProductSet);

// Check whether set contains the particular element or not and returns true or false
ProductSet.contains('HCL');
System.debug('Value of Set with all values '+ProductSet);

Plans

Il s'agit d'une paire clé / valeur qui contient la clé unique pour chaque valeur. La clé et la valeur peuvent être de n'importe quel type de données.

Example

L'exemple suivant représente la carte du nom du produit avec le code produit.

// Initialize the Map
Map<string, string> ProductCodeToProductName = new Map<string, string>
{'1000'=>'HCL', '1001'=>'H2SO4'};

// This statement would give as output as key value pair in Debug log
System.debug('value of ProductCodeToProductName'+ProductCodeToProductName);

Méthodes pour les cartes

Voici quelques exemples qui illustrent les méthodes qui peuvent être utilisées avec Map -

// Define a new map
Map<string, string> ProductCodeToProductName = new Map<string, string>();

// Insert a new key-value pair in the map where '1002' is key and 'Acetone' is value
ProductCodeToProductName.put('1002', 'Acetone');

// Insert a new key-value pair in the map where '1003' is key and 'Ketone' is value
ProductCodeToProductName.put('1003', 'Ketone');

// Assert that the map contains a specified key and respective value
System.assert(ProductCodeToProductName.containsKey('1002'));
System.debug('If output is true then Map contains the key and output is:'
   + ProductCodeToProductName.containsKey('1002'));

// Retrieves a value, given a particular key
String value = ProductCodeToProductName.get('1002');
System.debug('Value at the Specified key using get function: '+value);

// Return a set that contains all of the keys in the map
Set SetOfKeys = ProductCodeToProductName.keySet();
System.debug('Value of Set with Keys '+SetOfKeys);

Les valeurs de la carte peuvent ne pas être ordonnées et nous ne devons donc pas nous fier à l'ordre dans lequel les valeurs sont stockées et essayer d'accéder à la carte en utilisant toujours des clés. La valeur de la carte peut être nulle. Les clés de mappage lorsqu'elles sont déclarées String sont sensibles à la casse; par exemple, ABC et abc seront considérés comme des clés différentes et traités comme uniques.

Qu'est-ce qu'une classe?

Une classe est un modèle ou un plan à partir duquel des objets sont créés. Un objet est une instance d'une classe. C'est la définition standard de la classe. Les classes Apex sont similaires aux classes Java.

Par exemple, InvoiceProcessorclass décrit la classe qui contient toutes les méthodes et actions pouvant être effectuées sur la facture. Si vous créez une instance de cette classe, elle représentera alors la facture unique actuellement en contexte.

Créer des classes

Vous pouvez créer une classe dans Apex à partir de la Developer Console, de l'IDE Force.com Eclipse et de la page de détails de la classe Apex.

Depuis la Developer Console

Suivez ces étapes pour créer une classe Apex à partir de la Developer Console -

Step 1 - Allez dans Nom et cliquez sur la Developer Console.

Step 2 - Cliquez sur Fichier ⇒ Nouveau puis sur la classe Apex.

Depuis Force.com IDE

Suivez ces étapes pour créer une classe à partir de Force.com IDE -

Step 1 - Ouvrez l'IDE Force.com Eclipse

Step 2 - Créez un nouveau projet en cliquant sur Fichier ⇒ Nouveau ⇒ Classe Apex.

Step 3 - Fournissez le nom de la classe et cliquez sur OK.

Une fois cela fait, la nouvelle classe sera créée.

À partir de la page de détails de la classe Apex

Suivez ces étapes pour créer une classe à partir de la page de détails de la classe Apex -

Step 1 - Cliquez sur Nom ⇒ Configuration.

Step 2- Recherchez «Apex Class» et cliquez sur le lien. Cela ouvrira la page des détails de la classe Apex.

Step 3 - Cliquez sur «Nouveau», puis indiquez le nom de la classe, puis cliquez sur Enregistrer.

Structure de classe Apex

Vous trouverez ci-dessous un exemple de structure pour la définition de classe Apex.

Syntax

private | public | global
[virtual | abstract | with sharing | without sharing]
class ClassName [implements InterfaceNameList] [extends ClassName] {
   // Classs Body
}

Cette définition utilise une combinaison de modificateurs d'accès, de modes de partage, de nom de classe et de corps de classe. Nous examinerons toutes ces options plus en détail.

Example

Voici un exemple de structure pour la définition de classe Apex -

public class MySampleApexClass {       //Class definition and body
   public static Integer myValue = 0;  //Class Member variable
   public static String myString = ''; //Class Member variable
   
   public static Integer getCalculatedValue () {
   // Method definition and body
   // do some calculation
      myValue = myValue+10;
      return myValue;
   }
}

Modificateurs d'accès

Privé

Si vous déclarez le modificateur d'accès comme «Privé», alors cette classe ne sera connue que localement et vous ne pourrez pas accéder à cette classe en dehors de cette pièce particulière. Par défaut, les classes ont ce modificateur.

Publique

Si vous déclarez la classe comme «Public», cela implique que cette classe est accessible à votre organisation et à votre espace de noms défini. Normalement, la plupart des classes Apex sont définies avec ce mot clé.

Global

Si vous déclarez la classe comme «globale», elle sera accessible par tous les codes apex, quelle que soit votre organisation. Si vous avez défini une méthode avec un mot-clé de service Web, vous devez déclarer la classe contenant avec un mot-clé global.

Modes de partage

Parlons maintenant des différents modes de partage.

Avec partage

Il s'agit d'une fonctionnalité spéciale des classes Apex dans Salesforce. Lorsqu'une classe est spécifiée avec le mot-clé «Avec partage», les implications sont les suivantes: Lorsque la classe sera exécutée, elle respectera les paramètres d'accès et l'autorisation de profil de l'utilisateur. Supposons que l'action de l'utilisateur ait déclenché la mise à jour de l'enregistrement pour 30 enregistrements, mais que l'utilisateur n'a accès qu'à 20 enregistrements et que 10 enregistrements ne sont pas accessibles. Ensuite, si la classe exécute l'action pour mettre à jour les enregistrements, seuls 20 enregistrements seront mis à jour auxquels l'utilisateur a accès et le reste des 10 enregistrements ne sera pas mis à jour. Ceci est également appelé le mode utilisateur.

Sans partage

Même si l'Utilisateur n'a pas accès à 10 enregistrements sur 30, tous les 30 enregistrements seront mis à jour car la Classe s'exécute en mode Système, c'est-à-dire qu'elle a été définie avec le mot-clé Sans Partage. C'est ce qu'on appelle le mode système.

Virtuel

Si vous utilisez le mot-clé 'virtual', cela indique que cette classe peut être étendue et que les remplacements sont autorisés. Si les méthodes doivent être remplacées, les classes doivent être déclarées avec le mot clé virtual.

Abstrait

Si vous déclarez la classe comme «abstraite», alors elle ne contiendra que la signature de la méthode et non l'implémentation réelle.

Variables de classe

Syntax

[public | private | protected | global] [final] [static] data_type
variable_name [= value]

Dans la syntaxe ci-dessus -

  • Le type de données et le nom de la variable sont obligatoires
  • Les modificateurs d'accès et la valeur sont facultatifs.

Example

public static final Integer myvalue;

Méthodes de classe

Il existe deux modificateurs pour les méthodes de classe dans Apex: public ou protégé. Le type de retour est obligatoire pour la méthode et si la méthode ne renvoie rien, vous devez mentionner void comme type de retour. De plus, Body est également requis pour la méthode.

Syntax

[public | private | protected | global]
[override]
[static]

return_data_type method_name (input parameters) {
   // Method body goes here
}

Explication de la syntaxe

Les paramètres mentionnés entre crochets sont facultatifs. Cependant, les composants suivants sont essentiels -

  • return_data_type
  • method_name

Modificateurs d'accès pour les méthodes de classe

À l'aide des modificateurs d'accès, vous pouvez spécifier le niveau d'accès pour les méthodes de classe. Par exemple, la méthode publique sera accessible de n'importe où dans la classe et en dehors de la classe. La méthode privée ne sera accessible qu'au sein de la classe. Global sera accessible par toutes les classes Apex et peut être exposé en tant que méthode de service Web accessible par d'autres classes apex.

Example

//Method definition and body
public static Integer getCalculatedValue () {
   
   //do some calculation
   myValue = myValue+10;
   return myValue;
}

Cette méthode a le type de retour Integer et ne prend aucun paramètre.

Une méthode peut avoir des paramètres comme indiqué dans l'exemple suivant -

// Method definition and body, this method takes parameter price which will then be used 
// in method.

public static Integer getCalculatedValueViaPrice (Decimal price) {
   // do some calculation
   myValue = myValue+price;
   return myValue;
}

Constructeurs de classe

Un constructeur est un code qui est appelé lorsqu'un objet est créé à partir du plan de classe. Il porte le même nom que le nom de la classe.

Nous n'avons pas besoin de définir le constructeur pour chaque classe, car par défaut, un constructeur sans argument est appelé. Les constructeurs sont utiles pour l'initialisation de variables ou lorsqu'un processus doit être effectué au moment de l'initialisation de la classe. Par exemple, vous aimerez attribuer des valeurs à certaines variables Integer comme 0 lorsque la classe est appelée.

Example

// Class definition and body
public class MySampleApexClass2 {
   public static Double myValue;   // Class Member variable
   public static String myString;  // Class Member variable

   public MySampleApexClass2 () {
      myValue = 100; //initialized variable when class is called
   }

   public static Double getCalculatedValue () { // Method definition and body
      // do some calculation
      myValue = myValue+10;
      return myValue;
   }

   public static Double getCalculatedValueViaPrice (Decimal price) {
      // Method definition and body
      // do some calculation
      myValue = myValue+price; // Final Price would be 100+100=200.00
      return myValue;
   }
}

Vous pouvez également appeler la méthode de la classe via le constructeur. Cela peut être utile lors de la programmation d'Apex pour le contrôleur de force visuelle. Lorsque l'objet de classe est créé, le constructeur est appelé comme indiqué ci-dessous -

// Class and constructor has been instantiated
MySampleApexClass2 objClass = new MySampleApexClass2();
Double FinalPrice = MySampleApexClass2.getCalculatedValueViaPrice(100);
System.debug('FinalPrice: '+FinalPrice);

Surcharger les constructeurs

Les constructeurs peuvent être surchargés, c'est-à-dire qu'une classe peut avoir plus d'un constructeur défini avec des paramètres différents.

Example

public class MySampleApexClass3 {  // Class definition and body
   public static Double myValue;   // Class Member variable
   public static String myString;  // Class Member variable

   public MySampleApexClass3 () {
      myValue = 100; // initialized variable when class is called
      System.debug('myValue variable with no Overaloading'+myValue);
   }

   public MySampleApexClass3 (Integer newPrice) { // Overloaded constructor
      myValue = newPrice; // initialized variable when class is called
      System.debug('myValue variable with Overaloading'+myValue);
   }

      public static Double getCalculatedValue () { // Method definition and body
      // do some calculation
      myValue = myValue+10;
      return myValue;
   }

   public static Double getCalculatedValueViaPrice (Decimal price) {
      // Method definition and body
      // do some calculation
      myValue = myValue+price;
      return myValue;
   }
}

Vous pouvez exécuter cette classe comme nous l'avons exécutée dans l'exemple précédent.

// Developer Console Code
MySampleApexClass3 objClass = new MySampleApexClass3();
Double FinalPrice = MySampleApexClass3.getCalculatedValueViaPrice(100);
System.debug('FinalPrice: '+FinalPrice);

Une instance de classe est appelée Object. En termes de Salesforce, l'objet peut être de classe ou vous pouvez également créer un objet de sObject.

Création d'objets à partir de la classe

Vous pouvez créer un objet de classe comme vous l'avez peut-être fait en Java ou dans un autre langage de programmation orienté objet.

Voici un exemple de classe appelée MyClass -

// Sample Class Example
public class MyClass {
   Integer myInteger = 10;
   
   public void myMethod (Integer multiplier) {
      Integer multiplicationResult;
      multiplicationResult = multiplier*myInteger;
      System.debug('Multiplication is '+multiplicationResult);
   }
}

Il s'agit d'une classe d'instance, c'est-à-dire que pour appeler ou accéder aux variables ou méthodes de cette classe, vous devez créer une instance de cette classe et ensuite vous pouvez effectuer toutes les opérations.

// Object Creation
// Creating an object of class
MyClass objClass = new MyClass();

// Calling Class method using Class instance
objClass.myMethod(100);

Création d'un sObject

Les sObjects sont les objets de Salesforce dans lesquels vous stockez les données. Par exemple, Compte, Contact, etc., sont des objets personnalisés. Vous pouvez créer des instances d'objet de ces sObjects.

Voici un exemple d'initialisation de sObject et montre comment vous pouvez accéder au champ de cet objet particulier en utilisant la notation par points et attribuer les valeurs aux champs.

// Execute the below code in Developer console by simply pasting it
// Standard Object Initialization for Account sObject
Account objAccount = new Account(); // Object initialization
objAccount.Name = 'Testr Account'; // Assigning the value to field Name of Account
objAccount.Description = 'Test Account';
insert objAccount; // Creating record using DML
System.debug('Records Has been created '+objAccount);

// Custom sObject initialization and assignment of values to field
APEX_Customer_c objCustomer = new APEX_Customer_c ();
objCustomer.Name = 'ABC Customer';
objCustomer.APEX_Customer_Decscription_c = 'Test Description';
insert objCustomer;
System.debug('Records Has been created '+objCustomer);

Initialisation statique

Les méthodes et variables statiques ne sont initialisées qu'une seule fois lorsqu'une classe est chargée. Les variables statiques ne sont pas transmises dans le cadre de l'état d'affichage d'une page Visualforce.

Voici un exemple de méthode statique ainsi que de variable statique.

// Sample Class Example with Static Method
public class MyStaticClass {
   Static Integer myInteger = 10;
   
   public static void myMethod (Integer multiplier) {
      Integer multiplicationResult;
      multiplicationResult = multiplier * myInteger;
      System.debug('Multiplication is '+multiplicationResult);
   }
}

// Calling the Class Method using Class Name and not using the instance object
MyStaticClass.myMethod(100);

Static Variable Use

Les variables statiques ne seront instanciées qu'une seule fois lorsque la classe est chargée et ce phénomène peut être utilisé pour éviter la récursivité du déclencheur. La valeur de la variable statique sera la même dans le même contexte d'exécution et toute classe, déclencheur ou code en cours d'exécution peut s'y référer et empêcher la récursivité.

Une interface est comme une classe Apex dans laquelle aucune des méthodes n'a été implémentée. Il ne contient que les signatures de méthode, mais le corps de chaque méthode est vide. Pour utiliser une interface, une autre classe doit l'implémenter en fournissant un corps pour toutes les méthodes contenues dans l'interface.

Les interfaces sont principalement utilisées pour fournir la couche d'abstraction de votre code. Ils séparent l'implémentation de la déclaration de la méthode.

Prenons un exemple de notre société chimique. Supposons que nous devions offrir la remise aux clients Premium et Ordinaire et que les remises pour les deux seront différentes.

Nous allons créer une interface appelée DiscountProcessor.

// Interface
public interface DiscountProcessor {
   Double percentageDiscountTobeApplied(); // method signature only
}

// Premium Customer Class
public class PremiumCustomer implements DiscountProcessor {
   
   //Method Call
   public Double percentageDiscountTobeApplied () {
      
      // For Premium customer, discount should be 30%
      return 0.30;
   }
}

// Normal Customer Class
public class NormalCustomer implements DiscountProcessor {
   
   // Method Call
   public Double percentageDiscountTobeApplied () {
      
      // For Premium customer, discount should be 10%
      return 0.10;
   }
}

Lorsque vous implémentez l'interface, il est obligatoire d'implémenter la méthode de cette interface. Si vous n'implémentez pas les méthodes d'interface, une erreur sera générée. Vous devez utiliser des interfaces lorsque vous souhaitez rendre l'implémentation de la méthode obligatoire pour le développeur.

Interface Salesforce standard pour Batch Apex

SFDC possède des interfaces standard telles que Database.Batchable, Schedulable, etc. Par exemple, si vous implémentez l'interface Database.Batchable, vous devez implémenter les trois méthodes définies dans l'interface - Start, Execute et Finish.

Vous trouverez ci-dessous un exemple d'interface Database.Batchable fournie par Salesforce standard qui envoie des e-mails aux utilisateurs avec l'état du lot. Cette interface dispose de 3 méthodes, Démarrer, Exécuter et Terminer. En utilisant cette interface, nous pouvons implémenter la fonctionnalité Batchable et elle fournit également la variable BatchableContext que nous pouvons utiliser pour obtenir plus d'informations sur le Batch en cours d'exécution et pour exécuter d'autres fonctionnalités.

global class CustomerProessingBatch implements Database.Batchable<sobject7>,
Schedulable {
   // Add here your email address
   global String [] email = new String[] {'[email protected]'};

   // Start Method
   global Database.Querylocator start (Database.BatchableContext BC) {
      
      // This is the Query which will determine the scope of Records and fetching the same
      return Database.getQueryLocator('Select id, Name, APEX_Customer_Status__c,
         APEX_Customer_Decscription__c From APEX_Customer__c WHERE createdDate = today
         && APEX_Active__c = true');
   }

   // Execute method
   global void execute (Database.BatchableContext BC, List<sobject> scope) {
      List<apex_customer__c> customerList = new List<apex_customer__c>();
      List<apex_customer__c> updtaedCustomerList = new List<apex_customer__c>();
      
      for (sObject objScope: scope) {
         // type casting from generic sOject to APEX_Customer__c
         APEX_Customer__c newObjScope = (APEX_Customer__c)objScope ;
         newObjScope.APEX_Customer_Decscription__c = 'Updated Via Batch Job';
         newObjScope.APEX_Customer_Status__c = 'Processed';
         
         // Add records to the List
         updtaedCustomerList.add(newObjScope);
      }

      // Check if List is empty or not
      if (updtaedCustomerList != null && updtaedCustomerList.size()>0) {
         
         // Update the Records
         Database.update(updtaedCustomerList); System.debug('List Size
            '+updtaedCustomerList.size());
      }
   }

   // Finish Method
   global void finish(Database.BatchableContext BC) {
      Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
      
      // get the job Id
      AsyncApexJob a = [Select a.TotalJobItems, a.Status, a.NumberOfErrors,
      a.JobType, a.JobItemsProcessed, a.ExtendedStatus, a.CreatedById,
      a.CompletedDate From AsyncApexJob a WHERE id = :BC.getJobId()];
      System.debug('$$$ Jobid is'+BC.getJobId());
      
      // below code will send an email to User about the status
      mail.setToAddresses(email);
     
      // Add here your email address
      mail.setReplyTo('[email protected]');
      mail.setSenderDisplayName('Apex Batch Processing Module');
      mail.setSubject('Batch Processing '+a.Status);
      mail.setPlainTextBody('The Batch Apex job processed
         '+a.TotalJobItems+'batches with '+a.NumberOfErrors+'failures'+'Job Item
         processed are'+a.JobItemsProcessed);
      Messaging.sendEmail(new Messaging.Singleemailmessage [] {mail});
   }

   // Scheduler Method to scedule the class
   global void execute(SchedulableContext sc) {
      CustomerProessingBatch conInstance = new CustomerProessingBatch();
      database.executebatch(conInstance,100);
   }
}

Pour exécuter cette classe, vous devez exécuter le code ci-dessous dans la Developer Console.

CustomerProessingBatch objBatch = new CustomerProessingBatch ();
Database.executeBatch(objBatch);

Dans ce chapitre, nous verrons comment exécuter les différentes fonctionnalités de modification de base de données dans Salesforce. Il y a deux dit avec lesquels nous pouvons exécuter les fonctionnalités.

Déclarations DML

Les DML sont les actions qui sont effectuées pour effectuer une opération d'insertion, de mise à jour, de suppression, d'upsert, de restauration d'enregistrements, de fusion d'enregistrements ou de conversion de prospects.

Le DML est l'un des éléments les plus importants d'Apex, car presque tous les cas commerciaux impliquent des changements et des modifications de la base de données.

Méthodes de base de données

Toutes les opérations que vous pouvez effectuer à l'aide d'instructions DML peuvent également être effectuées à l'aide des méthodes Database. Les méthodes de base de données sont les méthodes système que vous pouvez utiliser pour effectuer des opérations DML. Les méthodes de base de données offrent plus de flexibilité que les instructions DML.

Dans ce chapitre, nous examinerons la première approche utilisant les instructions DML. Nous examinerons les méthodes de base de données dans un chapitre suivant.

Déclarations DML

Considérons maintenant à nouveau l'exemple de la société fournisseur de produits chimiques. Nos enregistrements de facture comportent des champs tels que Statut, Montant payé, Montant restant, Date de prochain paiement et Numéro de facture. Les factures qui ont été créées aujourd'hui et qui ont leur statut «En attente» doivent être mises à jour en «Payées».

Insérer une opération

L'opération d'insertion est utilisée pour créer de nouveaux enregistrements dans la base de données. Vous pouvez créer des enregistrements de n'importe quel objet standard ou personnalisé à l'aide de l'instruction Insert DML.

Example

Nous pouvons créer de nouveaux enregistrements dans l'objet APEX_Invoice__c au fur et à mesure que de nouvelles factures sont générées chaque jour pour les nouvelles commandes des clients. Nous allons d'abord créer un enregistrement client, puis nous pouvons créer un enregistrement de facture pour ce nouvel enregistrement client.

// fetch the invoices created today, Note, you must have at least one invoice 
// created today

List<apex_invoice__c> invoiceList = [SELECT id, Name, APEX_Status__c,
   createdDate FROM APEX_Invoice__c WHERE createdDate = today];

// create List to hold the updated invoice records
List<apex_invoice__c> updatedInvoiceList = new List<apex_invoice__c>();
APEX_Customer__c objCust = new APEX_Customer__C();
objCust.Name = 'Test ABC';

//DML for Inserting the new Customer Records
insert objCust;
for (APEX_Invoice__c objInvoice: invoiceList) {
   if (objInvoice.APEX_Status__c == 'Pending') {
      objInvoice.APEX_Status__c = 'Paid';
      updatedInvoiceList.add(objInvoice);
   }
}

// DML Statement to update the invoice status
update updatedInvoiceList;

// Prints the value of updated invoices
System.debug('List has been updated and updated values are' + updatedInvoiceList);

// Inserting the New Records using insert DML statement
APEX_Invoice__c objNewInvoice = new APEX_Invoice__c();
objNewInvoice.APEX_Status__c = 'Pending';
objNewInvoice.APEX_Amount_Paid__c = 1000;
objNewInvoice.APEX_Customer__c = objCust.id;

// DML which is creating the new Invoice record which will be linked with newly
// created Customer record
insert objNewInvoice;
System.debug('New Invoice Id is '+objNewInvoice.id+' and the Invoice Number is'
   + objNewInvoice.Name);

Opération de mise à jour

L'opération de mise à jour consiste à effectuer des mises à jour sur les enregistrements existants. Dans cet exemple, nous mettrons à jour le champ Statut d'un enregistrement de facture existant sur «Payé».

Example

// Update Statement Example for updating the invoice status. You have to create
and Invoice records before executing this code. This program is updating the
record which is at index 0th position of the List.

// First, fetch the invoice created today
List<apex_invoice__c> invoiceList = [SELECT id, Name, APEX_Status__c,
createdDate FROM APEX_Invoice__c];
List<apex_invoice__c> updatedInvoiceList = new List<apex_invoice__c>();

// Update the first record in the List
invoiceList[0].APEX_Status__c = 'Pending';
updatedInvoiceList.add(invoiceList[0]);

// DML Statement to update the invoice status
update updatedInvoiceList;

// Prints the value of updated invoices
System.debug('List has been updated and updated values of records are' 
   + updatedInvoiceList[0]);

Opération Upsert

L'opération Upsert est utilisée pour effectuer une opération de mise à jour et si les enregistrements à mettre à jour ne sont pas présents dans la base de données, créez également de nouveaux enregistrements.

Example

Supposons que les enregistrements client dans l'objet Client doivent être mis à jour. Nous mettrons à jour l'enregistrement client existant s'il est déjà présent, sinon nous en créerons un nouveau. Cela sera basé sur la valeur du champ APEX_External_Id__c. Ce champ sera notre champ pour identifier si les enregistrements sont déjà présents ou non.

Note - Avant d'exécuter ce code, veuillez créer un enregistrement dans l'objet Client avec la valeur du champ ID externe comme '12341', puis exécutez le code ci-dessous -

// Example for upserting the Customer records
List<apex_customer__c> CustomerList = new List<apex_customer__c>();
for (Integer i = 0; i < 10; i++) {
   apex_customer__c objcust=new apex_customer__c(name = 'Test' +i,
   apex_external_id__c='1234' +i);
   customerlist.add(objcust);
} //Upserting the Customer Records

upsert CustomerList;

System.debug('Code iterated for 10 times and created 9 records as one record with 
   External Id 12341 is already present');

for (APEX_Customer_c objCustomer: CustomerList) {
   if (objCustomer.APEX_External_Id_c == '12341') {
      system.debug('The Record which is already present is '+objCustomer);
   }
}

Supprimer l'opération

Vous pouvez effectuer l'opération de suppression à l'aide du DML Supprimer.

Example

Dans ce cas, nous supprimerons les factures qui ont été créées à des fins de test, c'est-à-dire celles qui contiennent le nom «Test».

Vous pouvez également exécuter cet extrait de code à partir de la console Developer sans créer la classe.

// fetch the invoice created today
List<apex_invoice__c> invoiceList = [SELECT id, Name, APEX_Status__c,
createdDate FROM APEX_Invoice__c WHERE createdDate = today];
List<apex_invoice__c> updatedInvoiceList = new List<apex_invoice__c>();
APEX_Customer__c objCust = new APEX_Customer__C();
objCust.Name = 'Test';

// Inserting the Customer Records
insert objCust;
for (APEX_Invoice__c objInvoice: invoiceList) {
   if (objInvoice.APEX_Status__c == 'Pending') {
      objInvoice.APEX_Status__c = 'Paid';
      updatedInvoiceList.add(objInvoice);
   }
}

// DML Statement to update the invoice status
update updatedInvoiceList;

// Prints the value of updated invoices
System.debug('List has been updated and updated values are' + updatedInvoiceList);

// Inserting the New Records using insert DML statement
APEX_Invoice__c objNewInvoice = new APEX_Invoice__c();
objNewInvoice.APEX_Status__c = 'Pending';
objNewInvoice.APEX_Amount_Paid__c = 1000;
objNewInvoice.APEX_Customer__c = objCust.id;

// DML which is creating the new record
insert objNewInvoice;
System.debug('New Invoice Id is' + objNewInvoice.id);

// Deleting the Test invoices from Database
// fetch the invoices which are created for Testing, Select name which Customer Name
// is Test.
List<apex_invoice__c> invoiceListToDelete = [SELECT id FROM APEX_Invoice__c
   WHERE APEX_Customer__r.Name = 'Test'];

// DML Statement to delete the Invoices
delete invoiceListToDelete;
System.debug('Success, '+invoiceListToDelete.size()+' Records has been deleted');

Annuler la suppression

Vous pouvez annuler la suppression de l'enregistrement qui a été supprimé et qui se trouve dans la corbeille. Toutes les relations que possède l'enregistrement supprimé seront également restaurées.

Example

Supposons que les enregistrements supprimés dans l'exemple précédent doivent être restaurés. Ceci peut être réalisé en utilisant l'exemple suivant. Le code de l'exemple précédent a été modifié pour cet exemple.

// fetch the invoice created today
List<apex_invoice__c> invoiceList = [SELECT id, Name, APEX_Status__c,
createdDate FROM APEX_Invoice__c WHERE createdDate = today];
List<apex_invoice__c> updatedInvoiceList = new List<apex_invoice__c>();
APEX_Customer__c objCust = new APEX_Customer__C();
objCust.Name = 'Test';

// Inserting the Customer Records
insert objCust;
for (APEX_Invoice__c objInvoice: invoiceList) {
   if (objInvoice.APEX_Status__c == 'Pending') {
      objInvoice.APEX_Status__c = 'Paid';
      updatedInvoiceList.add(objInvoice);
   }
}

// DML Statement to update the invoice status
update updatedInvoiceList;

// Prints the value of updated invoices
System.debug('List has been updated and updated values are' + updatedInvoiceList);

// Inserting the New Records using insert DML statement
APEX_Invoice__c objNewInvoice = new APEX_Invoice__c();
objNewInvoice.APEX_Status__c = 'Pending';
objNewInvoice.APEX_Amount_Paid__c = 1000;
objNewInvoice.APEX_Customer__c = objCust.id;

// DML which is creating the new record
insert objNewInvoice;
System.debug('New Invoice Id is '+objNewInvoice.id);

// Deleting the Test invoices from Database
// fetch the invoices which are created for Testing, Select name which Customer Name
// is Test.
List<apex_invoice__c> invoiceListToDelete = [SELECT id FROM APEX_Invoice__c
   WHERE APEX_Customer__r.Name = 'Test'];

// DML Statement to delete the Invoices
delete invoiceListToDelete;
system.debug('Deleted Record Count is ' + invoiceListToDelete.size());
System.debug('Success, '+invoiceListToDelete.size() + 'Records has been deleted');

// Restore the deleted records using undelete statement
undelete invoiceListToDelete;
System.debug('Undeleted Record count is '+invoiceListToDelete.size()+'. This should 
   be same as Deleted Record count');

Les méthodes de classe de base de données sont une autre façon de travailler avec les instructions DML qui sont plus flexibles que les instructions DML telles que l'insertion, la mise à jour, etc.

Différences entre les méthodes de base de données et les instructions DML

Déclarations DML Méthodes de base de données
La mise à jour partielle n'est pas autorisée. Par exemple, si vous avez 20 enregistrements dans la liste, tous les enregistrements seront mis à jour ou aucun. Une mise à jour partielle est autorisée. Vous pouvez spécifier la méthode Parameter in Database comme true ou false, true pour autoriser la mise à jour partielle et false pour ne pas autoriser la même chose.
Vous ne pouvez pas obtenir la liste des enregistrements de réussite et d'échec. Vous pouvez obtenir la liste des enregistrements de réussite et d'échec comme nous l'avons vu dans l'exemple.
Example - insérer listName Example - Database.insert (listName, False), où false indique qu'une mise à jour partielle n'est pas autorisée.

Insérer une opération

L'insertion de nouveaux enregistrements via des méthodes de base de données est également assez simple et flexible. Considérons le scénario précédent dans lequel, nous avons inséré de nouveaux enregistrements en utilisant les instructions DML. Nous allons insérer le même en utilisant les méthodes de base de données.

Exemple

// Insert Operation Using Database methods
// Insert Customer Records First using simple DML Statement. This Customer Record will be
// used when we will create Invoice Records
APEX_Customer__c objCust = new APEX_Customer__C();
objCust.Name = 'Test';
insert objCust; // Inserting the Customer Records

// Insert Operation Using Database methods
APEX_Invoice__c objNewInvoice = new APEX_Invoice__c();
List<apex_invoice__c> InvoiceListToInsert = new List<apex_invoice__c>();
objNewInvoice.APEX_Status__c = 'Pending';
objNewInvoice.APEX_Customer__c = objCust.id;
objNewInvoice.APEX_Amount_Paid__c = 1000;
InvoiceListToInsert.add(objNewInvoice);
Database.SaveResult[] srList = Database.insert(InvoiceListToInsert, false);

// Database method to insert the records in List
// Iterate through each returned result by the method

for (Database.SaveResult sr : srList) {
   if (sr.isSuccess()) {
      // This condition will be executed for successful records and will fetch the ids 
      // of successful records
      System.debug('Successfully inserted Invoice. Invoice ID: ' + sr.getId());
      // Get the invoice id of inserted Account
   } else {
      // This condition will be executed for failed records
      for(Database.Error objErr : sr.getErrors()) {
         System.debug('The following error has occurred.');
         
         // Printing error message in Debug log
         System.debug(objErr.getStatusCode() + ': ' + objErr.getMessage());
         System.debug('Invoice oject field which are affected by the error:' 
            + objErr.getFields());
      }
   }
}

Opération de mise à jour

Examinons maintenant notre exemple de business case en utilisant les méthodes de base de données. Supposons que nous devions mettre à jour le champ de statut de l'objet Facture, mais en même temps, nous avons également besoin d'informations telles que le statut des enregistrements, les identifiants des enregistrements ayant échoué, le nombre de succès, etc. pour connaître l'état de notre opération.

Exemple

Nous mettrons à jour le champ «Statut» de la facture si le statut est «En attente» et que la date de création est aujourd'hui.

Le code ci-dessous vous aidera à mettre à jour les enregistrements de facture à l'aide de la méthode Database.update. Créez également un enregistrement de facture avant d'exécuter ce code.

// Code to update the records using the Database methods
List<apex_invoice__c> invoiceList = [SELECT id, Name, APEX_Status__c,
   createdDate FROM APEX_Invoice__c WHERE createdDate = today];

// fetch the invoice created today
List<apex_invoice__c> updatedInvoiceList = new List<apex_invoice__c>();
for (APEX_Invoice__c objInvoice: invoiceList) {
   if (objInvoice.APEX_Status__c == 'Pending') {
      objInvoice.APEX_Status__c = 'Paid';
      updatedInvoiceList.add(objInvoice);    //Adding records to the list
   }
}

Database.SaveResult[] srList = Database.update(updatedInvoiceList, false);
// Database method to update the records in List

// Iterate through each returned result by the method
for (Database.SaveResult sr : srList) {
   if (sr.isSuccess()) {
      // This condition will be executed for successful records and will fetch
      // the ids of successful records
      System.debug('Successfully updated Invoice. Invoice ID is : ' + sr.getId());
   } else {
      // This condition will be executed for failed records
      for(Database.Error objErr : sr.getErrors()) {
         System.debug('The following error has occurred.');
         
         // Printing error message in Debug log
         System.debug(objErr.getStatusCode() + ': ' + objErr.getMessage());
         System.debug('Invoice oject field which are affected by the error:' 
            + objErr.getFields());
      }
   }
}

Nous examinerons uniquement les opérations d'insertion et de mise à jour dans ce didacticiel. Les autres opérations sont assez similaires à ces opérations et à ce que nous avons fait dans le dernier chapitre.

Chaque entreprise ou application a une fonctionnalité de recherche comme l'une des exigences de base. Pour cela, Salesforce.com propose deux approches majeures utilisant SOSL et SOQL. Discutons en détail de l'approche SOSL dans ce chapitre.

SOSL

La recherche de la chaîne de texte à travers l'objet et dans le champ sera effectuée à l'aide de SOSL. Il s'agit du langage de recherche d'objets Salesforce. Il a la capacité de rechercher une chaîne particulière sur plusieurs objets.

Les instructions SOSL s'évaluent en une liste de sObjects, où chaque liste contient les résultats de la recherche pour un type de sObject particulier. Les listes de résultats sont toujours renvoyées dans le même ordre que celui spécifié dans la requête SOSL.

Exemple de requête SOSL

Prenons une analyse de rentabilisation dans laquelle nous devons développer un programme qui peut rechercher une chaîne spécifiée. Supposons que nous devions rechercher la chaîne «ABC» dans le champ Nom du client de l'objet Facture. Le code va comme suit -

Tout d'abord, vous devez créer un seul enregistrement dans l'objet Facture avec le nom du client comme «ABC» afin que nous puissions obtenir un résultat valide lors de la recherche.

// Program To Search the given string in all Object
// List to hold the returned results of sObject generic type
List<list<SObject>> invoiceSearchList = new List<List<SObject>>();

// SOSL query which will search for 'ABC' string in Customer Name field of Invoice Object
invoiceSearchList = [FIND 'ABC*' IN ALL FIELDS RETURNING APEX_Invoice_c
   (Id,APEX_Customer_r.Name)];

// Returned result will be printed
System.debug('Search Result '+invoiceSearchList);

// Now suppose, you would like to search string 'ABC' in two objects,
// that is Invoice and Account. Then for this query goes like this:

// Program To Search the given string in Invoice and Account object,
// you could specify more objects if you want, create an Account with Name as ABC.

// List to hold the returned results of sObject generic type
List<List<SObject>> invoiceAndSearchList = new List<List<SObject>>();

// SOSL query which will search for 'ABC' string in Invoice and in Account object's fields
invoiceAndSearchList = [FIND 'ABC*' IN ALL FIELDS RETURNING APEX_Invoice__c
   (Id,APEX_Customer__r.Name), Account];

// Returned result will be printed
System.debug('Search Result '+invoiceAndSearchList);

// This list will hold the returned results for Invoice Object
APEX_Invoice__c [] searchedInvoice = ((List<APEX_Invoice_c>)invoiceAndSearchList[0]);

// This list will hold the returned results for Account Object
Account [] searchedAccount = ((List<Account>)invoiceAndSearchList[1]);
System.debug('Value of searchedInvoice'+searchedInvoice+'Value of searchedAccount'
   + searchedAccount);

SOQL

C'est presque la même chose que SOQL. Vous pouvez l'utiliser pour récupérer les enregistrements d'objets à partir d'un seul objet à la fois. Vous pouvez écrire des requêtes imbriquées et également récupérer les enregistrements de l'objet parent ou enfant sur lequel vous interrogez maintenant.

Nous explorerons SOQL dans le prochain chapitre.

Il s'agit du langage de requête d'objet Salesforce conçu pour fonctionner avec la base de données SFDC. Il ne peut rechercher un enregistrement sur un critère donné que dans un seul sObject.

Comme SOSL, il ne peut pas rechercher dans plusieurs objets, mais il prend en charge les requêtes imbriquées.

Exemple SOQL

Prenons notre exemple actuel de Chemical Company. Supposons que nous ayons besoin d'une liste d'enregistrements qui sont créés aujourd'hui et dont le nom de client n'est pas «test». Dans ce cas, nous devrons utiliser la requête SOQL comme indiqué ci-dessous -

// fetching the Records via SOQL
List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
InvoiceList = [SELECT Id, Name, APEX_Customer__r.Name, APEX_Status__c FROM
   APEX_Invoice__c WHERE createdDate = today AND APEX_Customer__r.Name != 'Test'];
// SOQL query for given criteria

// Printing the fetched records
System.debug('We have total '+InvoiceList.size()+' Records in List');

for (APEX_Invoice__c objInvoice: InvoiceList) {
   System.debug('Record Value is '+objInvoice); 
   // Printing the Record fetched
}

Vous pouvez exécuter la requête SOQL via l'éditeur de requête dans la console développeur comme indiqué ci-dessous.

Exécutez la requête ci-dessous dans la Developer Console. Recherchez les enregistrements de facture créés aujourd'hui.

SELECT Id, Name, APEX_Customer__r.Name, APEX_Status__c FROM APEX_Invoice__c
   WHERE createdDate = today

Vous devez sélectionner les champs pour lesquels vous avez besoin des valeurs, sinon cela peut générer des erreurs d'exécution.

Traverser les champs de relation

C'est l'une des parties les plus importantes de SFDC car nous devons souvent parcourir la relation d'objet parent enfant

En outre, il peut y avoir des cas où vous devez insérer deux enregistrements d'objets associés dans la base de données. Par exemple, l'objet Facture a une relation avec l'objet Client et, par conséquent, un Client peut avoir plusieurs factures.

Supposons que vous créez la facture et que vous devez ensuite associer cette facture au client. Vous pouvez utiliser le code suivant pour cette fonctionnalité -

// Now create the invoice record and relate it with the Customer object
// Before executing this, please create a Customer Records with Name 'Customer
// Creation Test'
APEX_Invoice__c objInvoice = new APEX_Invoice__c();

// Relating Invoice to customer via id field of Customer object
objInvoice.APEX_Customer__c = [SELECT id FROM APEX_Customer__c WHERE Name =
   'Customer Creation Test' LIMIT 1].id;
objInvoice.APEX_Status__c = 'Pending';
insert objInvoice;  //Creating Invoice
System.debug('Newly Created Invoice'+objInvoice);  //Newly created invoice

Exécutez cet extrait de code dans la Developer Console. Une fois exécuté, copiez l'ID de la facture depuis la console développeur, puis ouvrez-la dans SFDC comme indiqué ci-dessous. Vous pouvez voir que l'enregistrement Parent a déjà été affecté à l'enregistrement Facture comme indiqué ci-dessous.

Récupération des enregistrements enfants

Prenons maintenant un exemple dans lequel toutes les factures liées à un dossier client particulier doivent se trouver au même endroit. Pour cela, vous devez connaître le nom de la relation enfant. Pour voir le nom de la relation enfant, accédez à la page de détails du champ sur l'objet enfant et vérifiez la valeur «Relation enfant». Dans notre exemple, ce sont les factures ajoutées par __r à la fin.

Exemple

Dans cet exemple, nous devrons configurer des données, créer un client avec le nom comme enregistrement «Client ABC», puis ajouter 3 factures à ce client.

Maintenant, nous allons récupérer les factures du client «Client ABC». Voici la requête pour le même -

// Fetching Child Records using SOQL
List<apex_customer__c> ListCustomers = [SELECT Name, Id, 
   (SELECT id, Name FROM Invoices__r) FROM APEX_Customer__c WHERE Name = 'ABC Customer'];

// Query for fetching the Child records along with Parent
System.debug('ListCustomers '+ListCustomers); // Parent Record

List<apex_invoice__c> ListOfInvoices = ListCustomers[0].Invoices__r;
// By this notation, you could fetch the child records and save it in List
System.debug('ListOfInvoices values of Child '+ListOfInvoices);
// Child records

Vous pouvez voir les valeurs d'enregistrement dans les journaux de débogage.

Récupération du dossier parental

Supposons que vous deviez récupérer le nom du client de la facture dont la date de création est aujourd'hui, vous pouvez alors utiliser la requête ci-dessous pour la même chose -

Exemple

Récupérez la valeur de l'enregistrement parent avec l'objet enfant.

// Fetching Parent Record Field value using SOQL
List<apex_invoice__c> ListOfInvoicesWithCustomerName = new List<apex_invoice__c>();
ListOfInvoicesWithCustomerName = [SELECT Name, id, APEX_Customer__r.Name 
   FROM APEX_Invoice__c LIMIT 10];

// Fetching the Parent record's values
for (APEX_Invoice__c objInv: ListOfInvoicesWithCustomerName) {
   System.debug('Invoice Customer Name is '+objInv.APEX_Customer__r.Name);
   // Will print the values, all the Customer Records will be printed
}

Ici, nous avons utilisé la notation APEX_Customer__r.Name, où APEX_Customer__r est le nom de la relation parent, ici vous devez ajouter le __r à la fin du champ Parent, puis vous pouvez récupérer la valeur du champ parent.

Fonctions d'agrégation

SOQL a une fonction d'agrégation comme nous l'avons dans SQL. Les fonctions d'agrégation nous permettent de regrouper et de résumer les données. Comprenons maintenant la fonction en détail.

Supposons que vous vouliez savoir quel est le revenu moyen que nous obtenons du client «Client ABC», vous pouvez alors utiliser cette fonction pour prendre la moyenne.

Exemple

// Getting Average of all the invoices for a Perticular Customer
AggregateResult[] groupedResults = [SELECT
   AVG(APEX_Amount_Paid__c)averageAmount FROM APEX_Invoice__c WHERE
   APEX_Customer__r.Name = 'ABC Customer'];
Object avgPaidAmount = groupedResults[0].get('averageAmount');
System.debug('Total Average Amount Received From Customer ABC is '+avgPaidAmount);

Vérifiez la sortie dans les journaux de débogage. Notez que toute requête qui inclut une fonction d'agrégation renvoie ses résultats dans un tableau deAggregateResultobjets. AggregateResult est un sObject en lecture seule et n'est utilisé que pour les résultats de requête. Il est utile lorsque nous devons générer le rapport sur des données volumineuses.

Il existe également d'autres fonctions d'agrégation que vous pouvez utiliser pour effectuer un résumé des données.

MIN() - Cela peut être utilisé pour trouver la valeur minimale

MAX() - Cela peut être utilisé pour trouver la valeur maximale.

Liaison des variables Apex

Vous pouvez utiliser la variable Apex dans la requête SOQL pour récupérer les résultats souhaités. Les variables Apex peuvent être référencées par la notation Colon (:).

Exemple

// Apex Variable Reference
String CustomerName = 'ABC Customer';
List<apex_customer__c> ListCustomer = [SELECT Id, Name FROM APEX_Customer__c
   WHERE Name = :CustomerName];

// Query Using Apex variable
System.debug('ListCustomer Name'+ListCustomer); // Customer Name

La sécurité Apex fait référence au processus d'application des paramètres de sécurité et d'application des règles de partage lors de l'exécution du code. Les classes Apex ont des paramètres de sécurité qui peuvent être contrôlés via deux mots-clés.

Règles de sécurité et de partage des données

Apex s'exécute généralement dans un contexte système, c'est-à-dire avec les autorisations de l'utilisateur actuel. La sécurité au niveau du champ et les règles de partage ne sont pas prises en compte lors de l'exécution du code. Seul le code de bloc anonyme s'exécute avec l'autorisation de l'utilisateur qui exécute le code.

Notre code Apex ne doit pas exposer les données sensibles à l'utilisateur qui sont masquées via les paramètres de sécurité et de partage. Par conséquent, la sécurité Apex et l'application de la règle de partage sont les plus importantes.

Avec mot-clé de partage

Si vous utilisez ce mot-clé, le code Apex appliquera les paramètres de partage de l'utilisateur actuel au code Apex. Cela n'applique pas l'autorisation de profil, uniquement les paramètres de partage de niveau de données.

Prenons un exemple dans lequel, notre utilisateur a accès à 5 enregistrements, mais le nombre total d'enregistrements est de 10. Ainsi, lorsque la classe Apex sera déclarée avec le mot-clé "Avec partage", elle ne retournera que 5 enregistrements sur lesquels l'utilisateur a accès à.

Example

Tout d'abord, assurez-vous que vous avez créé au moins 10 enregistrements dans l'objet Client avec «Nom» de 5 enregistrements en tant que «Client ABC» et au repos 5 enregistrements en tant que «Client XYZ». Ensuite, créez une règle de partage qui partagera le «client ABC» avec tous les utilisateurs. Nous devons également nous assurer que nous avons défini l'OWD de l'objet Client comme Privé.

Collez le code ci-dessous dans le bloc Anonyme dans la Developer Console.

// Class With Sharing
public with sharing class MyClassWithSharing {
   // Query To fetch 10 records
   List<apex_customer__c> CustomerList = [SELECT id, Name FROM APEX_Customer__c LIMIT 10];
   
   public Integer executeQuery () {
      System.debug('List will have only 5 records and the actual records are' 
         + CustomerList.size()+' as user has access to'+CustomerList);
      Integer ListSize = CustomerList.size();
      return ListSize;
   }
}

// Save the above class and then execute as below
// Execute class using the object of class
MyClassWithSharing obj = new MyClassWithSharing();
Integer ListSize = obj.executeQuery();

Sans partage de mot-clé

Comme son nom l'indique, la classe déclarée avec ce mot-clé s'exécute en mode système, c'est-à-dire que, quel que soit l'accès de l'utilisateur à l'enregistrement, la requête récupère tous les enregistrements.

// Class Without Sharing
public without sharing class MyClassWithoutSharing {
   List<apex_customer__c> CustomerList = [SELECT id, Name FROM APEX_Customer__c LIMIT 10];
   
   // Query To fetch 10 records, this will return all the records
   public Integer executeQuery () {
      System.debug('List will have only 5 records and the actula records are'
         + CustomerList.size()+' as user has access to'+CustomerList);
      Integer ListSize = CustomerList.size();
      return ListSize;
   }
}
// Output will be 10 records.

Définition de la sécurité pour la classe Apex

Vous pouvez activer ou désactiver une classe Apex pour un profil particulier. Les étapes pour la même chose sont données ci-dessous. Vous pouvez déterminer quel profil doit avoir accès à quelle classe.

Définition de la sécurité des classes Apex à partir de la page de la liste des classes

Step 1 - Dans Configuration, cliquez sur Développer → Classes Apex.

Step 2- Cliquez sur le nom de la classe que vous souhaitez restreindre. Nous avons cliqué sur CustomerOperationClass.

Step 3 - Cliquez sur Sécurité.

Step 4 - Sélectionnez les profils que vous souhaitez activer dans la liste Profils disponibles et cliquez sur Ajouter, ou sélectionnez les profils que vous souhaitez désactiver dans la liste Profils activés et cliquez sur Supprimer.

Step 5 - Cliquez sur Enregistrer.

Définition de la sécurité Apex à partir d'un jeu d'autorisations

Step 1 - Dans Configuration, cliquez sur Gérer les utilisateurs → Ensembles d'autorisations.

Step 2 - Sélectionnez un jeu d'autorisations.

Step 3 - Cliquez sur Apex Class Access.

Step 4 - Cliquez sur Modifier.

Step 5 - Sélectionnez les classes Apex que vous souhaitez activer dans la liste Classes Apex disponibles et cliquez sur Ajouter, ou sélectionnez les classes Apex que vous souhaitez désactiver dans la liste Classes Apex activées et cliquez sur Supprimer.

Step 6 - Cliquez sur le bouton Enregistrer.

L'appel Apex fait référence au processus d'exécution de la classe Apex. La classe Apex ne peut être exécutée que lorsqu'elle est appelée via l'une des méthodes répertoriées ci-dessous -

  • Déclencheurs et bloc anonyme

  • Un déclencheur appelé pour des événements spécifiés

  • Apex asynchrone

  • Planification d'une classe Apex pour qu'elle s'exécute à des intervalles spécifiés ou exécution d'un travail par lots

  • Classe de services Web

  • Classe de service de messagerie Apex

  • Services Web Apex, qui permettent d'exposer vos méthodes via les services Web SOAP et REST

  • Contrôleurs Visualforce

  • Service de messagerie Apex pour traiter les e-mails entrants

  • Appel d'Apex à l'aide de JavaScript

  • La boîte à outils Ajax pour appeler les méthodes de service Web implémentées dans Apex

Nous allons maintenant comprendre quelques façons courantes d'invoquer Apex.

À partir de Exécuter un bloc anonyme

Vous pouvez appeler la classe Apex via exécuter anonyme dans la Developer Console comme indiqué ci-dessous -

Step 1 - Ouvrez la Developer Console.

Step 2 - Cliquez sur Debug.

Step 3- Exécuter la fenêtre anonyme s'ouvrira comme indiqué ci-dessous. Maintenant, cliquez sur le bouton Exécuter -

Step 4 - Ouvrez le journal de débogage lorsqu'il apparaîtra dans le volet Journaux.

Depuis le déclencheur

Vous pouvez également appeler une classe Apex à partir de Trigger. Les déclencheurs sont appelés lorsqu'un événement spécifié se produit et les déclencheurs peuvent appeler la classe Apex lors de l'exécution.

Voici l'exemple de code qui montre comment une classe est exécutée lorsqu'un déclencheur est appelé.

Exemple

// Class which will gets called from trigger
public without sharing class MyClassWithSharingTrigger {

   public static Integer executeQuery (List<apex_customer__c> CustomerList) {
      // perform some logic and operations here
      Integer ListSize = CustomerList.size();
      return ListSize;
   }
}

// Trigger Code
trigger Customer_After_Insert_Example on APEX_Customer__c (after insert) {
   System.debug('Trigger is Called and it will call Apex Class');
   MyClassWithSharingTrigger.executeQuery(Trigger.new);  // Calling Apex class and 
                                                         // method of an Apex class
}

// This example is for reference, no need to execute and will have detail look on 
// triggers later chapters.

À partir du code du contrôleur de page Visualforce

La classe Apex peut également être appelée à partir de la page Visualforce. Nous pouvons spécifier le contrôleur ou l'extension du contrôleur et la classe Apex spécifiée est appelée.

Exemple

VF Page Code

Apex Class Code (Controller Extension)

Les déclencheurs Apex sont comme des procédures stockées qui s'exécutent lorsqu'un événement particulier se produit. Un déclencheur s'exécute avant et après qu'un événement se soit produit sur l'enregistrement.

Syntaxe

trigger triggerName on ObjectName (trigger_events) { Trigger_code_block }

Exécution du déclencheur

Voici les événements sur lesquels nous pouvons lancer la gâchette -

  • insert
  • update
  • delete
  • merge
  • upsert
  • undelete

Exemple de déclenchement 1

Supposons que nous ayons reçu une exigence commerciale selon laquelle nous devons créer un enregistrement de facture lorsque le champ «Statut du client» du client passe à Actif à Inactif. Pour cela, nous allons créer un déclencheur sur l'objet APEX_Customer__c en suivant ces étapes -

Step 1 - Aller à sObject

Step 2 - Cliquez sur Client

Step 3 - Cliquez sur le bouton 'Nouveau' dans la liste associée Déclencheur et ajoutez le code de déclenchement comme indiqué ci-dessous.

// Trigger Code
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   List InvoiceList = new List();
   
   for (APEX_Customer__c objCustomer: Trigger.new) {
      
      if (objCustomer.APEX_Customer_Status__c == 'Active') {
         APEX_Invoice__c objInvoice = new APEX_Invoice__c();
         objInvoice.APEX_Status__c = 'Pending';
         InvoiceList.add(objInvoice);
      }
   }
   
   // DML to insert the Invoice List in SFDC
   insert InvoiceList;
}

Explication

Trigger.new- Il s'agit de la variable de contexte qui stocke les enregistrements actuellement dans le contexte du déclencheur, en cours d'insertion ou de mise à jour. Dans ce cas, cette variable contient les enregistrements de l'objet Client qui ont été mis à jour.

Il existe d'autres variables de contexte disponibles dans le contexte - trigger.old, trigger.newMap, trigger.OldMap.

Exemple de déclenchement 2

Le déclencheur ci-dessus s'exécutera lorsqu'il y aura une opération de mise à jour sur les enregistrements client. Supposons que l'enregistrement de facture ne doit être inséré que lorsque le statut du client passe de Inactif à Actif et pas à chaque fois; pour cela, nous pouvons utiliser une autre variable de contextetrigger.oldMap qui stockera la clé comme identifiant d'enregistrement et la valeur comme anciennes valeurs d'enregistrement.

// Modified Trigger Code
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
   
   for (APEX_Customer__c objCustomer: Trigger.new) {
      
      // condition to check the old value and new value
      if (objCustomer.APEX_Customer_Status__c == 'Active' &&
      
      trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
         APEX_Invoice__c objInvoice = new APEX_Invoice__c();
         objInvoice.APEX_Status__c = 'Pending';
         InvoiceList.add(objInvoice);
      }
   }
   
   // DML to insert the Invoice List in SFDC
   insert InvoiceList;
}

Explication

Nous avons utilisé la variable Trigger.oldMap qui, comme expliqué précédemment, est une variable de contexte qui stocke l'ID et l'ancienne valeur des enregistrements en cours de mise à jour.

Les modèles de conception sont utilisés pour rendre notre code plus efficace et pour éviter d'atteindre les limites du gouverneur. Les développeurs peuvent souvent écrire du code inefficace qui peut provoquer une instanciation répétée des objets. Cela peut entraîner un code inefficace et peu performant, et potentiellement la violation des limites du gouverneur. Cela se produit le plus souvent dans les déclencheurs, car ils peuvent fonctionner sur un ensemble d'enregistrements.

Nous verrons quelques stratégies de design pattern importantes dans ce chapitre.

Modèles de conception de déclencheurs en masse

Dans une analyse de rentabilisation réelle, il est possible que vous deviez traiter des milliers d'enregistrements en une seule fois. Si votre déclencheur n'est pas conçu pour gérer de telles situations, il peut échouer lors du traitement des enregistrements. Vous devez suivre certaines bonnes pratiques lors de la mise en œuvre des déclencheurs. Tous les déclencheurs sont des déclencheurs en bloc par défaut et peuvent traiter plusieurs enregistrements à la fois. Vous devez toujours prévoir de traiter plus d'un enregistrement à la fois.

Prenons une analyse de rentabilisation dans laquelle vous devez traiter un grand nombre d'enregistrements et vous avez écrit le déclencheur comme indiqué ci-dessous. C'est le même exemple que nous avions pris pour insérer l'enregistrement de facture lorsque le statut du client passe de Inactif à Actif.

// Bad Trigger Example
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   
   for (APEX_Customer__c objCustomer: Trigger.new) {
      
      if (objCustomer.APEX_Customer_Status__c == 'Active' && 
         trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
         
         // condition to check the old value and new value
         APEX_Invoice__c objInvoice = new APEX_Invoice__c();
         objInvoice.APEX_Status__c = 'Pending';
         insert objInvoice;   //DML to insert the Invoice List in SFDC
      }
   }
}

Vous pouvez maintenant voir que l'instruction DML a été écrite pour le bloc de boucle qui fonctionnera lors du traitement de quelques enregistrements seulement, mais lorsque vous traitez des centaines d'enregistrements, elle atteindra la limite de l'instruction DML par transaction qui est le governor limit. Nous examinerons en détail les limites du gouverneur dans un chapitre suivant.

Pour éviter cela, nous devons rendre le déclencheur efficace pour traiter plusieurs enregistrements à la fois.

L'exemple suivant vous aidera à comprendre la même chose -

// Modified Trigger Code-Bulk Trigger
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
   
   for (APEX_Customer__c objCustomer: Trigger.new) {
      
      if (objCustomer.APEX_Customer_Status__c == 'Active' &&
         trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
         
         //condition to check the old value and new value
         APEX_Invoice__c objInvoice = new APEX_Invoice__c();
         objInvoice.APEX_Status__c = 'Pending';
         InvoiceList.add(objInvoice);//Adding records to List
      }
   }
   
   insert InvoiceList;
   // DML to insert the Invoice List in SFDC, this list contains the all records 
   // which need to be modified and will fire only one DML
}

Ce déclencheur ne déclenchera qu'une seule instruction DML car il fonctionnera sur une liste et la liste contient tous les enregistrements qui doivent être modifiés.

De cette manière, vous pouvez éviter les limites du gouverneur d'instruction DML.

Classe d'aide au déclenchement

Ecrire tout le code dans trigger n'est pas non plus une bonne pratique. Par conséquent, vous devez appeler la classe Apex et déléguer le traitement de Trigger à la classe Apex comme indiqué ci-dessous. La classe Trigger Helper est la classe qui effectue tout le traitement du déclencheur.

Considérons à nouveau notre exemple de création d'enregistrement de facture.

// Below is the Trigger without Helper class
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
   
   for (APEX_Customer__c objCustomer: Trigger.new) {
      
      if (objCustomer.APEX_Customer_Status__c == 'Active' &&
         trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
         
         // condition to check the old value and new value
         APEX_Invoice__c objInvoice = new APEX_Invoice__c();
         objInvoice.APEX_Status__c = 'Pending';
         InvoiceList.add(objInvoice);
      }
   }
   
   insert InvoiceList; // DML to insert the Invoice List in SFDC
}

// Below is the trigger with helper class
// Trigger with Helper Class
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   CustomerTriggerHelper.createInvoiceRecords(Trigger.new, trigger.oldMap);
   // Trigger calls the helper class and does not have any code in Trigger
}

Classe d'assistance

public class CustomerTriggerHelper {
   public static void createInvoiceRecords (List<apex_customer__c>
   
   customerList, Map<id, apex_customer__c> oldMapCustomer) {
      List<apex_invoice__c> InvoiceList = new Listvapex_invoice__c>();
      
      for (APEX_Customer__c objCustomer: customerList) {
         
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            oldMapCustomer.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            
            // condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            
            // objInvoice.APEX_Status__c = 'Pending';
            InvoiceList.add(objInvoice);
         }
      }
      
      insert InvoiceList;  // DML to insert the Invoice List in SFDC
   }
}

En cela, tout le traitement a été délégué à la classe d'assistance et lorsque nous avons besoin d'une nouvelle fonctionnalité, nous pouvons simplement ajouter le code à la classe d'assistance sans modifier le déclencheur.

Déclencheur unique sur chaque sObject

Créez toujours un seul déclencheur sur chaque objet. Plusieurs déclencheurs sur le même objet peuvent provoquer le conflit et des erreurs s'il atteint les limites du gouverneur.

Vous pouvez utiliser la variable de contexte pour appeler les différentes méthodes de la classe d'assistance selon l'exigence. Prenons notre exemple précédent. Supposons que notre méthode createInvoice ne doit être appelée que lorsque l'enregistrement est mis à jour et sur plusieurs événements. Ensuite, nous pouvons contrôler l'exécution comme ci-dessous -

// Trigger with Context variable for controlling the calling flow
trigger Customer_After_Insert on APEX_Customer__c (after update, after insert) {
   
   if (trigger.isAfter && trigger.isUpdate) {
      // This condition will check for trigger events using isAfter and isUpdate
      // context variable
      CustomerTriggerHelper.createInvoiceRecords(Trigger.new);
      
      // Trigger calls the helper class and does not have any code in Trigger
      // and this will be called only when trigger ids after update
   }
}

// Helper Class
public class CustomerTriggerHelper {
   
   //Method To Create Invoice Records
   public static void createInvoiceRecords (List<apex_customer__c> customerList) {
      
      for (APEX_Customer__c objCustomer: customerList) {
         
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            
            // condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            objInvoice.APEX_Status__c = 'Pending';
            InvoiceList.add(objInvoice);
         }
      }
      
      insert InvoiceList; // DML to insert the Invoice List in SFDC
   }
}

Les limites d'exécution du gouverneur garantissent une utilisation efficace des ressources sur la plate-forme mutualisée Force.com. Il s'agit de la limite spécifiée par Salesforce.com sur l'exécution du code pour un traitement efficace.

Que sont les limites du gouverneur?

Comme nous le savons, Apex fonctionne dans un environnement multi-locataire, c'est-à-dire qu'une seule ressource est partagée par tous les clients et organisations. Donc, il est nécessaire de s'assurer que personne ne monopolise les ressources et donc Salesforce.com a créé l'ensemble de limites qui régit et limite l'exécution du code. Chaque fois que l'une des limites du gouverneur est franchie, une erreur se produira et arrêtera l'exécution du programme.

Du point de vue d'un développeur, il est important de s'assurer que notre code doit être évolutif et ne doit pas atteindre les limites.

Toutes ces limites sont appliquées par transaction. Une seule exécution de déclencheur est une transaction.

Comme nous l'avons vu, le modèle de conception du déclencheur permet d'éviter l'erreur de limite. Nous allons maintenant voir d'autres limites importantes.

Éviter la limite de requête SOQL

Vous ne pouvez émettre que 100 requêtes par transaction, c'est-à-dire que lorsque votre code émettra plus de 100 requêtes SOQL, il générera une erreur.

Exemple

Cet exemple montre comment la limite de requête SOQL peut être atteinte -

Le déclencheur suivant parcourt une liste de clients et met à jour la description de l'enregistrement enfant (Facture) avec la chaîne «Ok to Pay».

// Helper class:Below code needs o be checked.
public class CustomerTriggerHelper {
  
  public static void isAfterUpdateCall(Trigger.new) {
      createInvoiceRecords(trigger.new);//Method call
      updateCustomerDescription(trigger.new);
   }
   
   // Method To Create Invoice Records
   public static void createInvoiceRecords (List<apex_customer__c> customerList) {
      for (APEX_Customer__c objCustomer: customerList) {
         
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            
            // condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            objInvoice.APEX_Status__c = 'Pending';
            InvoiceList.add(objInvoice);
         }
      }
      insert InvoiceList; // DML to insert the Invoice List in SFDC
   }
   
   // Method to update the invoice records
   public static updateCustomerDescription (List<apex_customer__c> customerList) {
      for (APEX_Customer__c objCust: customerList) {
         List<apex_customer__c> invList = [SELECT Id, Name,
            APEX_Description__c FROM APEX_Invoice__c WHERE APEX_Customer__c = :objCust.id];
         
         // This query will fire for the number of records customer list has and will
         // hit the governor limit when records are more than 100
         for (APEX_Invoice__c objInv: invList) {
            objInv.APEX_Description__c = 'OK To Pay';
            update objInv;
            // Update invoice, this will also hit the governor limit for DML if large
            // number(150) of records are there
         }
      }
   }
}

Lorsque la méthode 'updateCustomerDescription' est appelée et que le nombre d'enregistrements client est supérieur à 100, elle atteindra la limite SOQL. Pour éviter cela, n'écrivez jamais la requête SOQL dans la boucle For. Dans ce cas, la requête SOQL a été écrite dans la boucle For.

Voici un exemple qui montrera comment éviter le DML ainsi que la limite SOQL. Nous avons utilisé la requête de relation imbriquée pour récupérer les enregistrements de facture et utilisé la variable de contextetrigger.newMap pour obtenir la carte des enregistrements d'identifiant et client.

// SOQL-Good Way to Write Query and avoid limit exception
// Helper Class
public class CustomerTriggerHelper {
   public static void isAfterUpdateCall(Trigger.new) {
      createInvoiceRecords(trigger.new);  //Method call
      updateCustomerDescription(trigger.new, trigger.newMap);
   }
   
   // Method To Create Invoice Records
   public static void createInvoiceRecords (List<apex_customer__c> customerList) {
      for (APEX_Customer__c objCustomer: customerList) {
         
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            
            // condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            objInvoice.APEX_Status__c = 'Pending';
            InvoiceList.add(objInvoice);
         }
      }
      insert InvoiceList; // DML to insert the Invoice List in SFDC
   }
   
   // Method to update the invoice records
   public static updateCustomerDescription (List<apex_customer__c>
      customerList, Map<id, apex_customer__c> newMapVariable) {
      List<apex_customer__c> customerListWithInvoice = [SELECT id,
         Name,(SELECT Id, Name, APEX_Description__c FROM APEX_Invoice__r) FROM
         APEX_Customer__c WHERE Id IN :newMapVariable.keySet()];
      
      // Query will be for only one time and fetches all the records
      List<apex_invoice__c> invoiceToUpdate = new
      List<apex_invoice__c>();
      
      for (APEX_Customer__c objCust: customerList) {
         for (APEX_Invoice__c objInv: invList) {
            objInv.APEX_Description__c = 'OK To Pay';
            invoiceToUpdate.add(objInv);
            // Add the modified records to List
         }
      }
      update invoiceToUpdate;
   }
}

Appels en masse DML

Cet exemple montre le déclencheur Bulk avec le modèle de classe d'assistance du déclencheur. Vous devez d'abord enregistrer la classe d'assistance, puis enregistrer le déclencheur.

Note - Collez le code ci-dessous dans la classe 'CustomerTriggerHelper' que nous avons créée précédemment.

// Helper Class
public class CustomerTriggerHelper {
   public static void isAfterUpdateCall(List<apex_customer__c> customerList,
      Map<id, apex_customer__c> mapIdToCustomers, Map<id, apex_customer__c>
      mapOldItToCustomers) {
      createInvoiceRecords(customerList, mapOldItToCustomers);   //Method call
      updateCustomerDescription(customerList,mapIdToCustomers,
      mapOldItToCustomers);
   }
   
   // Method To Create Invoice Records
   public static void createInvoiceRecords (List<apex_customer__c>
      customerList, Map<id, apex_customer__c> mapOldItToCustomers) {
      List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
      List<apex_customer__c> customerToInvoice = [SELECT id, Name FROM
         APEX_Customer__c LIMIT 1];
      
      for (APEX_Customer__c objCustomer: customerList) {
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            mapOldItToCustomers.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            //condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            objInvoice.APEX_Status__c = 'Pending';
            objInvoice.APEX_Customer__c = objCustomer.id;
            InvoiceList.add(objInvoice);
         }
      }
      system.debug('InvoiceList&&&'+InvoiceList);
      insert InvoiceList;
      // DML to insert the Invoice List in SFDC. This also follows the Bulk pattern
   }
   
   // Method to update the invoice records
   public static void updateCustomerDescription (List<apex_customer__c>
      customerList, Map<id, apex_customer__c> newMapVariable, Map<id,
      apex_customer__c> oldCustomerMap) {
      List<apex_customer__c> customerListWithInvoice = [SELECT id,
      Name,(SELECT Id, Name, APEX_Description__c FROM Invoices__r) FROM
         APEX_Customer__c WHERE Id IN :newMapVariable.keySet()];
   
      // Query will be for only one time and fetches all the records
      List<apex_invoice__c> invoiceToUpdate = new List<apex_invoice__c>();
      List<apex_invoice__c> invoiceFetched = new List<apex_invoice__c>();
      invoiceFetched = customerListWithInvoice[0].Invoices__r;
      system.debug('invoiceFetched'+invoiceFetched);
      system.debug('customerListWithInvoice****'+customerListWithInvoice);
   
      for (APEX_Customer__c objCust: customerList) {
         system.debug('objCust.Invoices__r'+objCust.Invoices__r);
         if (objCust.APEX_Active__c == true &&
            oldCustomerMap.get(objCust.id).APEX_Active__c == false) {
            for (APEX_Invoice__c objInv: invoiceFetched) {
               system.debug('I am in For Loop'+objInv);
               objInv.APEX_Description__c = 'OK To Pay';
               invoiceToUpdate.add(objInv);
               // Add the modified records to List
            }
         }
      }
     system.debug('Value of List ***'+invoiceToUpdate);
     update invoiceToUpdate;
      // This statement is Bulk DML which performs the DML on List and avoids
      // the DML Governor limit
   }
}

// Trigger Code for this class: Paste this code in 'Customer_After_Insert'
// trigger on Customer Object
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   CustomerTriggerHelper.isAfterUpdateCall(Trigger.new, trigger.newMap,
      trigger.oldMap);
   // Trigger calls the helper class and does not have any code in Trigger
}

Autres limites du gouverneur Salesforce

Le tableau suivant répertorie les limites importantes du régulateur.

La description Limite
Taille totale du tas 6 Mo / 12 Mo
Nombre total d'instructions DML émises 150
Nombre total d'enregistrements récupérés par une seule requête SOSL 2000
Nombre total de requêtes SOSL émises 20
Nombre total d'enregistrements récupérés par Database.getQueryLocator 10 000
Nombre total d'enregistrements récupérés par les requêtes SOQL 50000

Dans ce chapitre, nous allons comprendre le traitement par lots dans Apex. Prenons un scénario dans lequel nous traiterons quotidiennement un grand nombre d'enregistrements, probablement le nettoyage des données ou peut-être la suppression de certaines données inutilisées.

Qu'est-ce que Batch Apex?

Batch Apex est une exécution asynchrone de code Apex, spécialement conçue pour traiter le grand nombre d'enregistrements et offre une plus grande flexibilité dans les limites du gouverneur que le code synchrone.

Quand utiliser Batch Apex?

  • Lorsque vous souhaitez traiter un grand nombre d'enregistrements quotidiennement ou même à une heure précise, vous pouvez opter pour Batch Apex.

  • De plus, lorsque vous souhaitez qu'une opération soit asynchrone, vous pouvez implémenter l'Apex par lots. Batch Apex est présenté comme une interface qui doit être implémentée par le développeur. Les travaux par lots peuvent être appelés par programme au moment de l'exécution à l'aide d'Apex. Batch Apex fonctionne sur de petits lots d'enregistrements, couvrant l'intégralité de votre jeu d'enregistrements et décomposant le traitement en blocs de données gérables.

Utilisation de Batch Apex

Lorsque nous utilisons Batch Apex, nous devons implémenter l'interface fournie par Salesforce Database.Batchable, puis appeler la classe par programme.

Vous pouvez surveiller la classe en suivant ces étapes -

Pour surveiller ou arrêter l'exécution du travail par lots Apex Batch, accédez à Configuration → Surveillance → Travaux ou travaux Apex → Travaux Apex.

L'interface Database.Batchable a les trois méthodes suivantes qui doivent être implémentées -

  • Start
  • Execute
  • Finish

Comprenons maintenant chaque méthode en détail.

Début

La méthode Start est l'une des trois méthodes de l'interface Database.Batchable.

Syntax

global void execute(Database.BatchableContext BC, list<sobject<) {}

Cette méthode sera appelée au démarrage de la tâche Batch et collecte les données sur lesquelles la tâche Batch sera exécutée.

Tenez compte des points suivants pour comprendre la méthode -

  • Utilisez le Database.QueryLocatorobjet lorsque vous utilisez une requête simple pour générer la portée des objets utilisés dans le travail par lots. Dans ce cas, la limite de ligne de données SOQL sera contournée.

  • Utilisez l'objet itérable lorsque vous avez des critères complexes pour traiter les enregistrements. Database.QueryLocator détermine la portée des enregistrements qui doivent être traités.

Exécuter

Voyons maintenant la méthode Execute de l'interface Database.Batchable.

Syntax

global void execute(Database.BatchableContext BC, list<sobject<) {}

où, list <sObject <est retourné par la méthode Database.QueryLocator.

Cette méthode est appelée après la méthode Start et effectue tout le traitement requis pour le traitement par lots.

terminer

Nous allons maintenant discuter de la méthode Finish de l'interface Database.Batchable.

Syntax

global void finish(Database.BatchableContext BC) {}

Cette méthode est appelée à la fin et vous pouvez effectuer certaines activités de finition telles que l'envoi d'un e-mail contenant des informations sur les enregistrements de travaux par lots traités et leur statut.

Exemple Apex par lots

Prenons un exemple de notre société chimique existante et supposons que nous ayons l'obligation de mettre à jour le champ Statut du client et Description du client des enregistrements client qui ont été marqués comme actifs et qui ont créé la date comme aujourd'hui. Cela doit être fait quotidiennement et un e-mail doit être envoyé à un utilisateur sur l'état du traitement par lots. Mettez à jour le statut du client en tant que «traité» et la description du client en tant que «mise à jour via un traitement par lots».

// Batch Job for Processing the Records
global class CustomerProessingBatch implements Database.Batchable<sobject> {
   global String [] email = new String[] {'[email protected]'};
   // Add here your email address here
  
   // Start Method
   global Database.Querylocator start (Database.BatchableContext BC) {
      return Database.getQueryLocator('Select id, Name, APEX_Customer_Status__c,
      APEX_Customer_Decscription__c From APEX_Customer__c WHERE createdDate = today
      AND APEX_Active__c = true');
      // Query which will be determine the scope of Records fetching the same
   }
   
   // Execute method
   global void execute (Database.BatchableContext BC, List<sobject> scope) {
      List<apex_customer__c> customerList = new List<apex_customer__c>();
      List<apex_customer__c> updtaedCustomerList = new List<apex_customer__c>();
      
      // List to hold updated customer
      for (sObject objScope: scope) {
         APEX_Customer__c newObjScope = (APEX_Customer__c)objScope ;
         
         // type casting from generic sOject to APEX_Customer__c
         newObjScope.APEX_Customer_Decscription__c = 'Updated Via Batch Job';
         newObjScope.APEX_Customer_Status__c = 'Processed';
         updtaedCustomerList.add(newObjScope); // Add records to the List
         System.debug('Value of UpdatedCustomerList '+updtaedCustomerList);
      }
      
      if (updtaedCustomerList != null && updtaedCustomerList.size()>0) {
         // Check if List is empty or not
         Database.update(updtaedCustomerList); System.debug('List Size '
          + updtaedCustomerList.size());
         // Update the Records
      }
   }
   
   // Finish Method
   global void finish(Database.BatchableContext BC) {
      Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
      
      // Below code will fetch the job Id
      AsyncApexJob a = [Select a.TotalJobItems, a.Status, a.NumberOfErrors,
      a.JobType, a.JobItemsProcessed, a.ExtendedStatus, a.CreatedById,
      a.CompletedDate From AsyncApexJob a WHERE id = :BC.getJobId()];
      
      // get the job Id
      System.debug('$$$ Jobid is'+BC.getJobId());
      
      // below code will send an email to User about the status
      mail.setToAddresses(email);
      mail.setReplyTo('[email protected]'); // Add here your email address
      mail.setSenderDisplayName('Apex Batch Processing Module');
      mail.setSubject('Batch Processing '+a.Status);
      mail.setPlainTextBody('The Batch Apex job processed'
         + a.TotalJobItems+'batches with '+a.NumberOfErrors+'failures'+'Job Item
      processed are'+a.JobItemsProcessed);
      Messaging.sendEmail(new Messaging.Singleemailmessage [] {mail});
   }
}

Pour exécuter ce code, enregistrez-le d'abord, puis collez le code suivant dans Execute anonymous. Cela créera l'objet de la classe et la méthode Database.execute exécutera le travail par lots. Une fois le travail terminé, un e-mail sera envoyé à l'adresse e-mail spécifiée. Assurez-vous que vous disposez d'un dossier clientActive comme vérifié.

// Paste in Developer Console
CustomerProessingBatch objClass = new CustomerProessingBatch();
Database.executeBatch (objClass);

Une fois ce cours exécuté, vérifiez l'adresse e-mail que vous avez fournie à laquelle vous recevrez l'e-mail avec les informations. En outre, vous pouvez vérifier l'état du travail par lots via la page Surveillance et les étapes décrites ci-dessus.

Si vous vérifiez les journaux de débogage, vous pouvez trouver la taille de la liste qui indique le nombre d'enregistrements traités.

Limitations

Nous ne pouvons avoir que 5 traitements par lots à la fois. C'est l'une des limitations de Batch Apex.

Planification de la tâche Apex Batch à l'aide de la page de détails Apex

Vous pouvez planifier la classe Apex via la page de détails Apex comme indiqué ci-dessous -

Step 1 - Allez dans Setup ⇒ Apex Classes, cliquez sur Apex Classes.

Step 2 - Cliquez sur le bouton Planifier Apex.

Step 3 - Fournissez des détails.

Planification de la tâche Apex Batch à l'aide de l'interface de planification

Vous pouvez planifier le travail par lots Apex à l'aide de l'interface planifiable comme indiqué ci-dessous -

// Batch Job for Processing the Records
global class CustomerProessingBatch implements Database.Batchable<sobject> {
   global String [] email = new String[] {'[email protected]'};
   // Add here your email address here
   
   // Start Method
   global Database.Querylocator start (Database.BatchableContext BC) {
      return Database.getQueryLocator('Select id, Name, APEX_Customer_Status__c,
      APEX_Customer_Decscription__c From APEX_Customer__c WHERE createdDate = today
      AND APEX_Active__c = true');
      // Query which will be determine the scope of Records fetching the same
   }
   
   // Execute method
   global void execute (Database.BatchableContext BC, List<sobject> scope) {
      List<apex_customer__c> customerList = new List<apex_customer__c>();
      List<apex_customer__c> updtaedCustomerList = new
      List<apex_customer__c>();//List to hold updated customer
      
      for (sObject objScope: scope) {
         APEX_Customer__c newObjScope = (APEX_Customer__c)objScope ;//type
         casting from generic sOject to APEX_Customer__c
         newObjScope.APEX_Customer_Decscription__c = 'Updated Via Batch Job';
         newObjScope.APEX_Customer_Status__c = 'Processed';
         updtaedCustomerList.add(newObjScope);//Add records to the List
         System.debug('Value of UpdatedCustomerList '+updtaedCustomerList);
      }
      
      if (updtaedCustomerList != null && updtaedCustomerList.size()>0) {
         // Check if List is empty or not
         Database.update(updtaedCustomerList); System.debug('List Size'
            + updtaedCustomerList.size());
         // Update the Records
      }
   }
 
   // Finish Method
   global void finish(Database.BatchableContext BC) {
      Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
      
      // Below code will fetch the job Id
      AsyncApexJob a = [Select a.TotalJobItems, a.Status, a.NumberOfErrors,
      a.JobType, a.JobItemsProcessed, a.ExtendedStatus, a.CreatedById,
      a.CompletedDate From AsyncApexJob a WHERE id = :BC.getJobId()];//get the job Id
      System.debug('$$$ Jobid is'+BC.getJobId());
      
      // below code will send an email to User about the status
      mail.setToAddresses(email);
      mail.setReplyTo('[email protected]');//Add here your email address
      mail.setSenderDisplayName('Apex Batch Processing Module');
      mail.setSubject('Batch Processing '+a.Status);
      mail.setPlainTextBody('The Batch Apex job processed' 
         + a.TotalJobItems+'batches with '+a.NumberOfErrors+'failures'+'Job Item
      processed are'+a.JobItemsProcessed);
      Messaging.sendEmail(new Messaging.Singleemailmessage [] {mail});
   }
   
   // Scheduler Method to scedule the class
   global void execute(SchedulableContext sc) {
      CustomerProessingBatch conInstance = new CustomerProessingBatch();
      database.executebatch(conInstance,100);
   }
}

// Paste in Developer Console
CustomerProessingBatch objClass = new CustomerProcessingBatch();
Database.executeBatch (objClass);

Le débogage est une partie importante de tout développement de programmation. Dans Apex, nous avons certains outils qui peuvent être utilisés pour le débogage. L'une d'elles est la méthode system.debug () qui imprime la valeur et la sortie de la variable dans les journaux de débogage.

Nous pouvons utiliser les deux outils suivants pour le débogage -

  • Developer Console
  • Journaux de débogage

Débogage via la Developer Console

Vous pouvez utiliser la console développeur et exécuter une fonctionnalité anonyme pour le débogage de l'Apex comme ci-dessous -

Example

Considérez notre exemple existant de récupération des enregistrements clients qui ont été créés aujourd'hui. Nous voulons simplement savoir si la requête renvoie les résultats ou non et si oui, nous vérifierons la valeur de List.

Collez le code ci-dessous dans Exécuter la fenêtre anonyme et suivez les étapes que nous avons effectuées pour ouvrir la fenêtre Exécuter anonyme.

Step 1 - Ouvrez la console développeur

Step 2 - Ouvrez le Exécuter anonyme à partir de 'Debug' comme indiqué ci-dessous.

Step 3 - Ouvrez la fenêtre Execute Anonymous et collez le code suivant et cliquez sur Exécuter.

// Debugging The Apex
List<apex_customer__c> customerList = new List<apex_customer__c>();
customerList = [SELECT Id, Name FROM APEX_Customer__c WHERE CreatedDate =
today];
// Our Query
System.debug('Records on List are '+customerList+' And Records are '+customerList);
// Debug statement to check the value of List and Size

Step 4 - Ouvrez les journaux comme indiqué ci-dessous.

Step 5 - Entrez «UTILISATEUR» dans la condition de filtre comme indiqué ci-dessous.

Step 6 - Ouvrez l'instruction USER DEBUG comme indiqué ci-dessous.

Débogage via les journaux de débogage

Vous pouvez également déboguer la même classe via les journaux de débogage. Supposons que vous ayez un déclencheur dans l'objet Client et qu'il doit être débogué pour certaines valeurs de variable, vous pouvez le faire via les journaux de débogage comme indiqué ci-dessous -

Il s'agit du code de déclenchement qui met à jour le champ Description si le client modifié est actif et que vous souhaitez vérifier les valeurs des variables et des enregistrements actuellement dans la portée -

trigger CustomerTrigger on APEX_Customer__c (before update) {
   List<apex_customer__c> customerList = new List<apex_customer__c>();
   for (APEX_Customer__c objCust: Trigger.new) {
      System.debug('objCust current value is'+objCust);
      
      if (objCust.APEX_Active__c == true) {
         objCust.APEX_Customer_Description__c = 'updated';
         System.debug('The record which has satisfied the condition '+objCust);
      }
   }
}

Suivez les étapes ci-dessous pour générer les journaux de débogage.

Step 1- Définissez les journaux de débogage pour votre utilisateur. Allez dans Configuration et tapez «Journal de débogage» dans la fenêtre de configuration de la recherche, puis cliquez sur Lien.

Step 2 - Définissez les journaux de débogage comme suit.

Step 3- Entrez le nom de l'utilisateur à configurer. Entrez votre nom ici.

Step 4 - Modifiez les enregistrements client au fur et à mesure qu'un événement doit se produire pour générer le journal de débogage.

Step 5- Allez à nouveau dans la section des journaux de débogage. Ouvrez les journaux de débogage et cliquez sur Réinitialiser.

Step 6 - Cliquez sur le lien de visualisation du premier journal de débogage.

Step 7 - Recherchez la chaîne «USER» en utilisant la recherche du navigateur comme indiqué ci-dessous.

L'instruction de débogage affichera la valeur du champ auquel nous avons défini le point.

Les tests font partie intégrante d'Apex ou de tout autre développement d'application. Dans Apex, nous avons des classes de test distinctes à développer pour tous les tests unitaires.

Classes de test

Dans SFDC, le code doit avoir une couverture de code de 75% pour être déployé en production. Cette couverture de code est effectuée par les classes de test. Les classes de test sont les extraits de code qui testent les fonctionnalités d'autres classes Apex.

Écrivons une classe de test pour l'un de nos codes que nous avons écrit précédemment. Nous écrirons une classe de test pour couvrir notre code de classe Trigger et Helper. Vous trouverez ci-dessous la classe de déclencheur et d'assistance qui doit être couverte.

// Trigger with Helper Class
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   CustomerTriggerHelper.createInvoiceRecords(Trigger.new, trigger.oldMap);
      //Trigger calls the helper class and does not have any code in Trigger
}

// Helper Class:
public class CustomerTriggerHelper {
   public static void createInvoiceRecords (List<apex_customer__c>
      
      customerList, Map<id, apex_customer__c> oldMapCustomer) {
      List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
      
      for (APEX_Customer__c objCustomer: customerList) {
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            oldMapCustomer.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            
            // condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            objInvoice.APEX_Status__c = 'Pending';
            objInvoice.APEX_Customer__c = objCustomer.id;
            InvoiceList.add(objInvoice);
         }
      }
      insert InvoiceList;  // DML to insert the Invoice List in SFDC
   }
}

Créer une classe de test

Dans cette section, nous allons comprendre comment créer une classe de test.

Création de données

Nous devons créer des données pour la classe de test dans notre classe de test elle-même. La classe de test par défaut n'a pas accès aux données de l'organisation, mais si vous définissez @isTest (voirAllData = true), elle aura également accès aux données de l'organisation.

Annotation @isTest

En utilisant cette annotation, vous avez déclaré qu'il s'agissait d'une classe de test et qu'elle ne sera pas comptabilisée dans la limite de code totale de l'organisation.

Mot clé testMethod

Les méthodes de test unitaire sont les méthodes qui ne prennent pas d'arguments, ne livrent aucune donnée dans la base de données, n'envoient aucun e-mail et sont déclarées avec le mot clé testMethod ou l'annotation isTest dans la définition de méthode. En outre, les méthodes de test doivent être définies dans des classes de test, c'est-à-dire des classes annotées avec isTest.

Nous avons utilisé la méthode de test «myUnitTest» dans nos exemples.

Test.startTest () et Test.stopTest ()

Ce sont les méthodes de test standard qui sont disponibles pour les classes de test. Ces méthodes contiennent l'événement ou l'action pour lequel nous simulerons notre test. Comme dans cet exemple, nous allons tester notre classe de déclencheur et d'assistance pour simuler le déclencheur d'incendie en mettant à jour les enregistrements comme nous l'avons fait pour démarrer et arrêter le bloc. Cela fournit également une limite de gouverneur distincte au code qui est dans le bloc de démarrage et d'arrêt.

System.assert ()

Cette méthode vérifie la sortie souhaitée avec le réel. Dans ce cas, nous nous attendons à ce qu'un enregistrement de facture soit inséré, nous avons donc ajouté assert pour vérifier la même chose.

Example

/**
* This class contains unit tests for validating the behavior of Apex classes
* and triggers.
*
* Unit tests are class methods that verify whether a particular piece
* of code is working properly. Unit test methods take no arguments,
* commit no data to the database, and are flagged with the testMethod
* keyword in the method definition.
*
* All test methods in an organization are executed whenever Apex code is deployed
* to a production organization to confirm correctness, ensure code
* coverage, and prevent regressions. All Apex classes are
* required to have at least 75% code coverage in order to be deployed
* to a production organization. In addition, all triggers must have some code coverage.
*
* The @isTest class annotation indicates this class only contains test
* methods. Classes defined with the @isTest annotation do not count against
* the organization size limit for all Apex scripts.
*
* See the Apex Language Reference for more information about Testing and Code Coverage.
*/

@isTest
private class CustomerTriggerTestClass {
   static testMethod void myUnitTest() {
      //Create Data for Customer Objet
      APEX_Customer__c objCust = new APEX_Customer__c();
      objCust.Name = 'Test Customer';
      objCust.APEX_Customer_Status__c = 'Inactive';
      insert objCust;
      
      // Now, our trigger will fire on After update event so update the Records
      Test.startTest();    // Starts the scope of test
      objCust.APEX_Customer_Status__c = 'Active';
      update objCust;
      Test.stopTest();     // Ends the scope of test
      
      // Now check if it is giving desired results using system.assert
      // Statement.New invoice should be created
      List<apex_invoice__c> invList = [SELECT Id, APEX_Customer__c FROM
         APEX_Invoice__c WHERE APEX_Customer__c = :objCust.id];
      system.assertEquals(1,invList.size());
      // Check if one record is created in Invoivce sObject
   }
}

Exécution de la classe de test

Suivez les étapes ci-dessous pour exécuter la classe de test -

Step 1 - Allez dans les classes Apex ⇒ cliquez sur le nom de la classe 'CustomerTriggerTestClass'.

Step 2 - Cliquez sur le bouton Exécuter le test comme indiqué.

Step 3 - Vérifier l'état

Step 4 - Vérifiez maintenant la classe et le déclencheur pour lesquels nous avons écrit le test

Classe

Déclencheur

Nos tests sont réussis et terminés.

Qu'est-ce que le déploiement dans SFDC?

Jusqu'à présent, nous avons développé du code dans Developer Edition, mais dans un scénario réel, vous devez effectuer ce développement dans Sandbox, puis vous devrez peut-être le déployer dans un autre environnement de sandbox ou de production et cela s'appelle le déploiement. En bref, il s'agit du déplacement des métadonnées d'une organisation à une autre. La raison en est que vous ne pouvez pas développer Apex dans votre organisation de production Salesforce. Les utilisateurs en direct qui accèdent au système pendant que vous développez peuvent déstabiliser vos données ou corrompre votre application.

Outils disponibles pour le déploiement -

  • IDE Force.com
  • Ensembles de modifications
  • API SOAP
  • Outil de migration Force.com

Comme nous utilisons l'édition Developer à des fins de développement et d'apprentissage, nous ne pouvons pas utiliser le jeu de modifications ou d'autres outils qui nécessitent l'entreprise SFDC ou une autre édition payante. Par conséquent, nous allons élaborer la méthode de déploiement de Force.com IDE dans ce didacticiel.

IDE Force.com Eclipse

Step 1 - Ouvrez Eclipse et ouvrez le déclencheur de classe qui doit être déployé.

Step 2 - Une fois que vous avez cliqué sur «Déployer sur le serveur», saisissez le nom d'utilisateur et le mot de passe de l'organisation dans laquelle le composant doit être déployé.

En exécutant les étapes mentionnées ci-dessus, vos composants Apex seront déployés dans l'organisation cible.

Déploiement à l'aide de l'ensemble de modifications

Vous pouvez déployer des règles de validation, des règles de workflow, des classes Apex et un déclencheur d'une organisation à une autre en les connectant via les paramètres de déploiement. Dans ce cas, les organisations doivent être connectées.

Pour ouvrir la configuration du déploiement, suivez les étapes ci-dessous. N'oubliez pas que cette fonctionnalité n'est pas disponible dans la Developer Edition -

Step 1 - Accédez à Configuration et recherchez «Déployer».

Step 2 - Cliquez sur 'Outbound Change Set' afin de créer un ensemble de modifications à déployer.

Step 3 - Ajoutez des composants pour modifier l'ensemble en utilisant le bouton «Ajouter», puis Enregistrer et cliquez sur Télécharger.

Step 4 - Accédez à l'organisation cible et cliquez sur l'ensemble de modifications entrantes et enfin cliquez sur déployer.

Appels d'API SOAP à déployer

Nous aurons juste un petit aperçu de cette méthode car ce n'est pas une méthode couramment utilisée.

Vous pouvez utiliser les appels de méthode ci-dessous pour déployer vos métadonnées.

  • compileAndTest()
  • compileClasses()
  • compileTriggers()

Outil de migration Force.com

Cet outil est utilisé pour le déploiement scripté. Vous devez télécharger l'outil Force.com Migration, puis vous pouvez effectuer le déploiement basé sur des fichiers. Vous pouvez télécharger l'outil de migration Force.com, puis effectuer le déploiement par script.