codemitte/force-toolkit-bundle
Installation:
composer require codemitte/force-toolkit-bundle
Add to config/bundles.php:
Codemitte\ForceToolkitBundle\CodemitteForceToolkitBundle::class => ['all' => true],
Configuration:
Define config/packages/codemitte_force_toolkit.yaml:
codemitte_force_toolkit:
soap:
wsdl: '%env(SF_WSDL_URL)%' # e.g., 'https://login.salesforce.com/services/Soap/u/26.0/partner.wsdl'
username: '%env(SF_USERNAME)%'
password: '%env(SF_PASSWORD)%'
security_token: '%env(SF_SECURITY_TOKEN)%'
trace: '%kernel.debug%' # Enable for debugging
First Use Case: Inject the client into a service/controller:
use Codemitte\ForceToolkitBundle\Service\ForceClient;
class MyController extends AbstractController {
public function __construct(private ForceClient $forceClient) {}
public function index() {
$query = "SELECT Id, Name FROM Account LIMIT 10";
$results = $this->forceClient->query($query);
return $this->render('accounts/index.html.twig', ['accounts' => $results]);
}
}
SOAP API Calls:
Use the ForceClient for standard operations:
// Query
$results = $forceClient->query("SELECT Id, Name FROM Account");
// QueryMore (for large datasets)
$queryLocator = $forceClient->query("SELECT Id FROM Account");
$moreResults = $forceClient->queryMore($queryLocator);
// Upsert
$forceClient->upsert("Account", ["Name" => "Test Account"], "External_Id__c");
// Describe (metadata)
$accountDesc = $forceClient->describe("Account");
Metadata Operations:
Leverage .describeX() methods for schema introspection:
// Get field descriptions
$fields = $forceClient->describeFields("Account");
// Get object names
$objects = $forceClient->describeGlobal();
Bulk API (Limited):
Use runBulkQuery() for large datasets (if supported by the underlying toolkit):
$bulkResults = $forceClient->runBulkQuery("SELECT Id FROM Account");
Dependency Injection:
Prefer injecting ForceClient over creating instances manually. Override the service in config/services.yaml if needed:
services:
App\Service\CustomForceService:
arguments:
$forceClient: '@codemitte_force_toolkit.client'
Error Handling:
Wrap calls in try-catch blocks to handle SoapFault exceptions:
try {
$results = $forceClient->query("INVALID_SOQL");
} catch (SoapFault $e) {
$this->addFlash('error', 'Salesforce Error: ' . $e->getMessage());
}
Dynamic SOQL:
Use sprintf or template engines for dynamic queries:
$query = sprintf("SELECT Id, Name FROM Account WHERE Name LIKE '%%%s%%'", $searchTerm);
Batch Processing:
For large datasets, implement pagination with queryMore:
$queryLocator = $forceClient->query("SELECT Id FROM Account");
do {
$results = $forceClient->queryMore($queryLocator);
// Process $results
} while (!empty($results->done));
Deprecation Warnings:
SalesforceClientBundle or SalesforceMapperBundle.Force.com Toolkit for PHP 5.3 is outdated (PHP 5.3 EOL: 2014). Test thoroughly in a sandbox.SOAP Limitations:
guzzlehttp/guzzle for Bulk API 2.0.soap.timeout in config if calls hang (default may be too low for large orgs).Metadata Quirks:
.describeX() methods may return cached data. Force refresh with:
$forceClient->describe("Account", true); // Pass `true` to bypass cache
describeFields().Performance:
SELECT *). Explicitly list needed fields to reduce payload size.trace: true in debug mode to inspect raw SOAP requests/responses (check var/log/dev.log).Enable SOAP Traces:
Set trace: true in config and check logs for raw SOAP XML:
codemitte_force_toolkit:
soap:
trace: true
Common Errors:
INVALID_SESSION_ID: Token expired. Reauthenticate or check security_token.MALFORMED_QUERY: Validate SOQL syntax using Salesforce SOQL Explorer.FIELD_INTEGRITY_EXCEPTION: Check field constraints (e.g., required fields, picklist values).Unit Testing:
Mock ForceClient in tests:
$mockClient = $this->createMock(ForceClient::class);
$mockClient->method('query')->willReturn(new \stdClass()); // Mock response
$service = new MyService($mockClient);
Custom SOAP Services: The bundle provides a base SOAP interface. Extend it for Apex web services:
// config/services.yaml
services:
App\Service\CustomApexService:
arguments:
$client: '@codemitte_force_toolkit.client'
$wsdl: 'https://yourorg.my.salesforce.com/services/Soap/u/26.0/0DFXXXXXXXXXXXXXXXX'
Event Listeners:
Subscribe to codemitte_force_toolkit.soap.response events to intercept responses:
use Codemitte\ForceToolkitBundle\Event\SoapResponseEvent;
public function onSoapResponse(SoapResponseEvent $event) {
$response = $event->getResponse();
// Modify or log $response
}
Configuration Overrides:
Override default config in config/packages/override/codemitte_force_toolkit.yaml:
codemitte_force_toolkit:
soap:
timeout: 60 # Increase timeout for large orgs
proxy: 'http://proxy.example.com:8080' # For corporate networks
SOQL Optimization:
Use FORCE.COM functions (e.g., GEOLOCATION(), DISTANCE()) for spatial queries:
$query = "SELECT Id, Name, BillingCity FROM Account
WHERE DISTANCE(GEOLOCATION(BillingCity, BillingState, BillingPostalCode), GEOLOCATION('New York', 'NY', '10001'), 'mi') < 100";
Bulkify Logic:
For batch operations, use Database.Batchable via Apex (call from PHP) instead of PHP loops.
Environment Variables:
Store credentials in .env:
SF_WSDL_URL=https://login.salesforce.com/services/Soap/u/26.0/partner.wsdl
SF_USERNAME=your@email.com
SF_PASSWORD=yourpassword
SF_SECURITY_TOKEN=yourtoken
How can I help you explore Laravel packages today?