Apex Programming
Apex Basics
public class MyApexClass {
// Class variables
private String name;
public Integer count { get; set; }
// Constructor
public MyApexClass() {
name = 'Default';
count = 0;
}
// Method with parameters
public String greet(String personName) {
return 'Hello, ' + personName + '!';
}
// Static method
public static Integer incrementCount(Integer current) {
return current + 1;
}
}
// Interface definition
public interface MyInterface {
void doSomething();
}
// Exception class
public class MyException extends Exception {
// Custom exception properties/methods
}
DML Operations
Account acc = new Account(Name = 'Test Account');
insert acc;
// Update records
acc.Name = 'Updated Account';
update acc;
// Upsert (insert or update)
upsert acc;
// Delete records
delete acc;
// Undelete records
undelete acc;
// Bulk DML operations
List<Account> accounts = new List<Account>();
for (Integer i = 0; i < 10; i++) {
accounts.add(new Account(Name = 'Account ' + i));
}
insert accounts;
// Database methods with options
Database.SaveResult sr = Database.insert(acc, false);
List<Database.SaveResult> results = Database.insert(accounts, false);
// Check DML results
for (Database.SaveResult result : results) {
if (result.isSuccess()) {
System.debug('Successfully created account: ' + result.getId());
} else {
for (Database.Error err : result.getErrors()) {
System.debug('Error: ' + err.getMessage());
}
}
}
SOQL & SOSL
SOQL Queries
List<Account> accounts = [SELECT Id, Name FROM Account];
// Query with WHERE clause
List<Account> accounts = [SELECT Id, Name FROM Account WHERE Industry = 'Technology'];
// Query with relationship fields
List<Contact> contacts = [SELECT Id, Name, Account.Name FROM Contact];
// Query with ORDER BY and LIMIT
List<Account> accounts = [SELECT Id, Name FROM Account ORDER BY Name DESC LIMIT 10];
// Aggregate queries
AggregateResult[] groupedResults = [SELECT COUNT(Id) total, Industry FROM Account GROUP BY Industry];
for (AggregateResult ar : groupedResults) {
System.debug('Industry: ' + ar.get('Industry'));
System.debug('Count: ' + ar.get('total'));
}
// Dynamic SOQL
String accountName = 'Test%';
String query = 'SELECT Id, Name FROM Account WHERE Name LIKE :accountName';
List<Account> accounts = Database.query(query);
// SOQL For Loop (handles large result sets)
for (Account acc : [SELECT Id, Name FROM Account]) {
System.debug('Account Name: ' + acc.Name);
}
// Query with bind variables
String industry = 'Technology';
List<Account> accounts = [SELECT Id, Name FROM Account WHERE Industry = :industry];
SOSL Queries
List<List<SObject>> searchList = [FIND 'Test' IN ALL FIELDS RETURNING Account(Id, Name), Contact];
// Extract results from SOSL query
List<Account> accounts = (List<Account>)searchList[0];
List<Contact> contacts = (List<Contact>)searchList[1];
// SOSL with WHERE clause
List<List<SObject>> searchList = [FIND 'Test' IN ALL FIELDS RETURNING Account(Id, Name WHERE Industry = 'Technology')];
// SOSL with multiple search groups
List<List<SObject>> searchList = [FIND 'Test OR Demo' IN ALL FIELDS RETURNING Account, Contact];
// Dynamic SOSL
String searchQuery = 'FIND \'Test*\' IN ALL FIELDS RETURNING Account (Id, Name), Contact';
List<List<SObject>> searchList = Search.query(searchQuery);
// SOSL with LIMIT and ORDER BY
List<List<SObject>> searchList = [FIND 'Test' IN ALL FIELDS RETURNING Account(Id, Name ORDER BY Name LIMIT 10)];
// SOSL with different search locations
List<List<SObject>> searchList = [FIND 'Test' IN NAME FIELDS RETURNING Account];
// SOSL with email fields search
List<List<SObject>> searchList = [FIND 'example.com' IN EMAIL FIELDS RETURNING Contact(Id, Name, Email)];
Triggers & Batch Apex
Apex Triggers
trigger AccountTrigger on Account (before insert, before update, after insert, after update) {
// Trigger context variables
if (Trigger.isBefore) {
if (Trigger.isInsert) {
// Before insert logic
for (Account acc : Trigger.new) {
// Set default values
acc.Description = 'Created by trigger';
}
}
else if (Trigger.isUpdate) {
// Before update logic
for (Account acc : Trigger.new) {
Account oldAcc = Trigger.oldMap.get(acc.Id);
if (acc.Name != oldAcc.Name) {
acc.Description = 'Name changed from ' + oldAcc.Name + ' to ' + acc.Name;
}
}
}
}
else if (Trigger.isAfter) {
if (Trigger.isInsert) {
// After insert logic
List<Task> tasks = new List<Task>();
for (Account acc : Trigger.tasks.add(new Task(
Subject = 'Follow up on new account',
WhatId = acc.Id,
Status = 'Not Started'
));
}
insert tasks;
}
}
}
// Trigger handler pattern (recommended)
trigger AccountTrigger on Account (before insert, before update) {
AccountTriggerHandler.handleBeforeInsertUpdate(Trigger.new, Trigger.oldMap);
}
Batch Apex
global class AccountUpdateBatch implements Database.Batchable<SObject> {
// Start method
global Database.QueryLocator start(Database.BatchableContext bc) {
return Database.getQueryLocator(
'SELECT Id, Name, Description FROM Account WHERE CreatedDate = TODAY'
);
}
// Execute method
global void execute(Database.BatchableContext bc, List<Account> scope) {
List<Account> accountsToUpdate = new List<Account>();
for (Account acc : scope) {
acc.Description = 'Updated by batch job on ' + System.today();
accountsToUpdate.add(acc);
}
update accountsToUpdate;
}
// Finish method
global void finish(Database.BatchableContext bc) {
// Execute any post-processing operations
AsyncApexJob job = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email FROM AsyncApexJob WHERE Id = :bc.getJobId()];
System.debug('Batch job completed with status: ' + job.Status);
}
}
// Executing a batch job
AccountUpdateBatch batchJob = new AccountUpdateBatch();
Database.executeBatch(batchJob, 100); // 100 records per batch
// Schedule a batch job
String cronExpr = '0 0 2 * * ?'; // Run at 2 AM every day
System.schedule('Daily Account Update', cronExpr, new AccountUpdateBatch());
// Batchable with state
global class StatefulBatch implements Database.Batchable<SObject>, Database.Stateful {
global Integer recordsProcessed = 0;
global Database.QueryLocator start(Database.BatchableContext bc) {
return Database.getQueryLocator('SELECT Id FROM Account');
}
global void execute(Database.BatchableContext bc, List<Account> scope) {
recordsProcessed += scope.size();
}
global void finish(Database.BatchableContext bc) {
System.debug('Total records processed: ' + recordsProcessed);
}
}
Lightning Web Components
LWC Basics
import { LightningElement, track, wire } from 'lwc';
import getContacts from '@salesforce/apex/ContactController.getContacts';
export default class MyComponent extends LightningElement {
@track contacts = [];
@track error;
searchKey = '';
// Wire method to get data from Apex
@wire(getContacts, { searchKey: '$searchKey' })
wiredContacts({ error, data }) {
if (data) {
this.contacts = data;
this.error = undefined;
} else if (error) {
this.error = error;
this.contacts = [];
}
}
// Handle user input
handleSearchChange(event) {
this.searchKey = event.target.value;
}
// Method to create a new contact
createContact() {
this.template.querySelector('c-contact-form').show();
}
}
// Apex controller (ContactController.cls)
public with sharing class ContactController {
@AuraEnabled(cacheable=true)
public static List<Contact> getContacts(String searchKey) {
String query = 'SELECT Id, Name, Email, Phone FROM Contact';
if (searchKey != null && searchKey != '') {
query += ' WHERE Name LIKE \'%' + String.escapeSingleQuotes(searchKey) + '%\'';
}
return Database.query(query);
}
}
LWC HTML Template
<template>
<div class="slds-m-around_medium">
<h1>Contact Manager</h1>
<!-- Search input -->
<div class="slds-grid slds-gutters">
<div class="slds-col">
<lightning-input
type="search"
value="{searchKey}"
onchange="{handleSearchChange}"
label="Search"
placeholder="Search contacts...">
</lightning-input>
</div>
<div class="slds-col slds-size_1-of-4">
<lightning-button
label="New Contact"
variant="brand"
onclick="{createContact}">
</lightning-button>
</div>
</div>
<!-- Display error if any -->
<template if:true="{error}">
<div class="slds-notify slds-notify_alert slds-theme_error">
<span class="slds-assistive-text">Error</span>
<span class="slds-icon_container slds-icon-utility-error">
<lightning-icon icon-name="utility:error"></lightning-icon>
</span>
<h2>{error.body.message}</h2>
</div>
</template>
<!-- Contacts list -->
<template if:true="{contacts}">
<div class="slds-card">
<ul class="slds-list slds-list_vertical">
<template for:each="{contacts}" for:item="contact">
<li key="{contact.Id}" class="slds-list__item">
<div class="slds-grid slds-wrap">
<div class="slds-col slds-size_1-of-2">
<b>{contact.Name}</b>
</div>
<div class="slds-col slds-size_1-of-2">
<a href="tel:{contact.Phone}">{contact.Phone}</a>
</div>
</div>
</li>
</template>
</ul>
</div>
</template>
</div>
<!-- Contact form component -->
<c-contact-form></c-contact-form>
</template>
Integration & Deployment
REST API Integration
@RestResource(urlMapping='/Account/*')
global with sharing class AccountManager {
// HTTP GET method
@HttpGet
global static Account getAccount() {
RestRequest request = RestContext.request;
String accountId = request.requestURI.substring(request.requestURI.lastIndexOf('/')+1);
Account result = [SELECT Id, Phone, Website FROM Account WHERE Id = :accountId];
return result;
}
// HTTP POST method
@HttpPost
global static String createAccount(String name, String phone, String website) {
Account acc = new Account();
acc.Name = name;
acc.Phone = phone;
acc.Website = website;
insert acc;
return acc.Id;
}
// HTTP PATCH method
@HttpPatch
global static String updateAccount() {
RestRequest request = RestContext.request;
String accountId = request.requestURI.substring(request.requestURI.lastIndexOf('/')+1);
Account acc = [SELECT Id FROM Account WHERE Id = :accountId];
Map<String, Object> params = (Map<String, Object>)JSON.deserializeUntyped(request.requestbody.toString());
for (String fieldName : params.keySet()) {
acc.put(fieldName, params.get(fieldName));
}
update acc;
return 'Account updated successfully';
}
}
// Callout to external REST API
public class HttpCalloutService {
public static String makeGetCallout(String endpoint) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint(endpoint);
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
return response.getBody();
} else {
throw new CalloutException('HTTP callout failed with status: ' + getStatusCode());
}
}
}
Deployment & Tools
# Login to org
sfdx force:auth:web:login -a "MyOrg"
# Create a scratch org
sfdx force:org:create -f config/project-scratch-def.json -a "MyScratchOrg" -s
# Push source to org
sfdx force:source:push -u "MyScratchOrg"
# Pull changes from org
sfdx force:source:pull -u "MyScratchOrg"
# Run Apex tests
sfdx force:apex:test:run -u "MyScratchOrg" -r "human"
# Open org
sfdx force:org:open -u "MyScratchOrg"
# Retrieve metadata
sfdx force:source:retrieve -m "ApexClass,CustomObject"
# Deploy metadata
sfdx force:source:deploy -m "ApexClass:MyClass,CustomObject:Account"
# Create a new Apex class
sfdx force:apex:class:create -n "MyNewClass" -d force-app/main/default/classes
# Create a new LWC
sfdx force:lightning:component:create -n "myComponent" -d force-app/main/default/lwc
# Generate password for user
sfdx force:user:password:generate -u "MyScratchOrg"
# Display org info
sfdx force:org:display -u "MyScratchOrg"
# List all orgs
sfdx force:org:list
# Delete a scratch org
sfdx force:org:delete -u "MyScratchOrg"
# Package version commands
sfdx force:package:version:create -p "MyPackage" -d force-app -w 10
sfdx force:package:version:list
sfdx force:package:version:promote -p "04t..."
Salesforce Resources
Useful Links
- Developer Documentation: Salesforce Developer Docs
- Trailhead: Salesforce Trailhead
- Developer Console: In-app tool for debugging and development
- Developer Forums: Salesforce Developer Community
- GitHub Repositories: Salesforce Official GitHub
- Salesforce CLI: Command Line Interface
- Developer Blog: Salesforce Developer Blog
- Podcasts: Salesforce Developers, Good Day Sir! Podcast
Best Practices
// Bad practice - SOQL inside loop
for (Account acc : accounts) {
List<Contact> contacts = [SELECT Id FROM Contact WHERE AccountId = :acc.Id]; // Avoid!
}
// Good practice - bulk SOQL
Set<Id> accountIds = new Set<Id>();
for (Account acc : accounts) {
accountIds.add(acc.Map<Id, List<Contact>> accountContacts = new Map<Id, List<Contact>>();
for (con : [SELECT Id, AccountId FROM Contact WHERE AccountId IN :accountIds]) {
if (!accountContacts.containsKey(con.AccountId)) {
accountContacts.put(con.AccountId, new List<Contact>());
}
accountContacts.get(con.AccountId).add(con);
}
// Avoid hardcoding IDs
// Bad practice
Account acc = [SELECT Id FROM Account WHERE Id = '001...']; // Avoid!
// Good practice - use custom settings or custom metadata
String accountId = AppConfig__c.getInstance().DefaultAccountId__c;
Account acc = [SELECT Id FROM极 Account WHERE Id = :accountId];
// Use limits methods to avoid governor limits
Integer soqlQueries = Limits.getQueries();
Integer soqlLimit = Limits.getLimitQueries();
System.debug('SOQL queries used: ' + soqlQueries + ' of ' + soqlLimit);
// Use @future appropriately for async operations
@future
public static void processRecordsAsync(Set<Id> recordIds) {
// Async processing logic
}
// Use exception handling
try {
// Code that might fail
insert records;
} catch (DmlException e) {
System.debug('DML Exception: ' + e.getMessage());
// Handle exception appropriately
}
Comprehensive Salesforce Admin & Developer Cheatsheet Reference
This Salesforce Admin & Developer cheatsheet on Nikhil Learn Hub collects syntax, commands, and practical snippets for quick revision. Explore Salesforce objects, Apex, SOQL, automation tools, and CRM concepts with clear examples and quick notes.
Use the reference cards and examples above during coding sessions; return here instead of scattered searches when you need dependable reminders. Follow the Salesforce learning roadmap when you want structured lessons beyond one-page lookups.
Quick lookup coverage
- Syntax, commands, and API signatures
- Copy-ready examples and common patterns
- Terminology for coursework and interviews
- Cross-links to the matching learning roadmap
How to study with this sheet
- Production debugging and tuning reminders
- Security, performance, or scale cautions
- Integration with adjacent stacks on this site
- Deeper study through tutorials and roadmaps
Who Should Use This Cheatsheet
Students, self-taught developers, and professionals who need fast Salesforce Admin & Developer lookups during labs, debugging, or interview revision should keep this page bookmarked.
Related Resources on Nikhil Learn Hub
- Salesforce learning roadmapstructured learning path for the same technology
- Cheatsheets hubbrowse all quick-reference sheets
- Technology hubtutorials, roadmaps, and practice hubs