phpforce/salesforce-bundle
Symfony bundle for integrating with Salesforce using the PHPForce/Force.com Toolkit. Provides service configuration and helpers for connecting to Salesforce APIs, making authenticated requests, and working with Salesforce data from your Symfony app.
Installation Add the bundle via Composer:
composer require phpforce/salesforce-bundle
Enable the bundle in config/bundles.php:
return [
// ...
Phpforce\SalesforceBundle\PhpforceSalesforceBundle::class => ['all' => true],
];
Configuration
Define credentials in config/packages/phpforce_salesforce.yaml:
phpforce_salesforce:
client_id: '%env(SF_CLIENT_ID)%'
client_secret: '%env(SF_CLIENT_SECRET)%'
username: '%env(SF_USERNAME)%'
password: '%env(SF_PASSWORD)%'
security_token: '%env(SF_SECURITY_TOKEN)%'
domain: '%env(SF_DOMAIN)%' # 'login' or 'test'
First Use Case Fetch a single Account record:
use Phpforce\SalesforceBundle\Service\SalesforceService;
class AccountController extends AbstractController
{
public function show(SalesforceService $sfService)
{
$account = $sfService->get('Account', '001XXXXXXXXXXXX');
return $this->json($account);
}
}
CRUD Operations
// Create
$newAccount = $sfService->create('Account', [
'Name' => 'Test Account',
'Description' => 'Created via API'
]);
// Update
$sfService->update('Account', '001XXXXXXXXXXXX', ['Description' => 'Updated']);
// Delete
$sfService->delete('Account', '001XXXXXXXXXXXX');
Querying Data
// SOQL Query
$accounts = $sfService->query("SELECT Id, Name FROM Account WHERE AnnualRevenue > 1000000");
// Bulk Query (for large datasets)
$sfService->bulkQuery("SELECT Id FROM Account");
Metadata Operations
// Describe an object
$accountDesc = $sfService->describe('Account');
// List all objects
$objects = $sfService->getObjectDescriptions();
Bulk API Usage
$job = $sfService->createBulkJob('AccountInsert');
$job->addBatch(['Name' => 'Batch 1']);
$job->close();
SalesforceService into controllers/services.try {
$result = $sfService->query("SELECT Id FROM NonExistentObject");
} catch (\Phpforce\Exception\SalesforceException $e) {
$this->addFlash('error', $e->getMessage());
}
phpforce_salesforce:
debug: true
Authentication Issues
INVALID_SESSION_ID or INVALID_LOGIN errors.security_token (if using password auth) and ensure credentials are correct. For OAuth, check token expiration.refreshToken() method if tokens expire:
$sfService->refreshToken();
SOQL Limitations
LIMIT clauses and paginate results:
$query = "SELECT Id FROM Account";
$results = $sfService->query($query, ['limit' => 1000]);
Bulk API Delays
$jobId = $sfService->createBulkJob('AccountInsert')->getJobId();
$status = $sfService->getBulkJobStatus($jobId);
Field API Names
AnnualRevenue vs. AnnualRevenue__c for custom fields).describe() to fetch correct API names:
$fields = $sfService->describe('Account')['fields'];
debug: true in config to log raw API responses.getLastRequest() and getLastResponse() on SalesforceService for debugging:
$lastRequest = $sfService->getLastRequest();
$this->addFlash('debug', print_r($lastRequest, true));
getApiUsage():
$usage = $sfService->getApiUsage();
$this->addFlash('info', sprintf('Used %d/%d API calls', $usage['numRequests'], $usage['limit']));
Custom Adapters
Override the default SalesforceService to add custom logic:
class CustomSalesforceService extends SalesforceService
{
public function customQuery(string $soql, array $options = [])
{
// Add custom logic (e.g., retry logic, logging)
return parent::query($soql, $options);
}
}
Event Listeners
Subscribe to salesforce.before_request and salesforce.after_response events in Symfony’s event dispatcher:
# config/services.yaml
services:
App\EventListener\SalesforceListener:
tags:
- { name: kernel.event_listener, event: salesforce.before_request, method: onBeforeRequest }
Custom Metadata
Extend the bundle’s metadata handling by implementing Phpforce\Metadata\MetadataInterface.
Async Processing Use Symfony’s Messenger component to handle long-running Bulk API jobs:
$message = new ProcessBulkJobMessage($jobId);
$this->messageBus->dispatch($message);
How can I help you explore Laravel packages today?