commercetools/php-sdk
Deprecated PHP SDK for commercetools Composable Commerce. Provides native PHP models/helpers, IDE autocompletion, object mapping, i18n, and an OAuth2 client with caching and async/concurrent request support. Requires PHP 5.6+ (Guzzle).
Installation
composer require commercetools/php-sdk
(Note: Only use this for legacy projects; migrate to PHP SDK V2 for new projects.)
Configure Client
Create a client instance in config/services.php:
'commercetools' => [
'client_id' => env('CT_CLIENT_ID'),
'client_secret' => env('CT_CLIENT_SECRET'),
'token_url' => env('CT_TOKEN_URL'),
'api_url' => env('CT_API_URL'),
'project_key' => env('CT_PROJECT_KEY'),
'cache' => [
'enabled' => env('CT_CACHE_ENABLED', false),
'ttl' => env('CT_CACHE_TTL', 300),
],
],
Register a service provider in config/app.php:
Commercetools\Client\Provider::class,
First Use Case: Fetch a Product
use Commercetools\Client\ClientBuilder;
use Commercetools\Client\Http\GuzzleHttpClient;
$client = ClientBuilder::withClientCredentialsFlow(
env('CT_CLIENT_ID'),
env('CT_CLIENT_SECRET'),
env('CT_TOKEN_URL')
)->withProjectKey(env('CT_PROJECT_KEY'))
->withHttpClient(new GuzzleHttpClient())
->build();
$product = $client->getById('products', '12345678-1234-1234-1234-123456789012');
CRUD Operations Use fluent methods for common actions:
// Create
$product = $client->create('products', $productData);
// Update
$updatedProduct = $client->update('products', $product->getId(), $updateActions);
// Delete
$client->delete('products', $product->getId());
Querying with Search
Leverage the Search class for complex queries:
$search = new \Commercetools\Client\Search();
$search->addQuery('name:test-product');
$search->addSort('name asc');
$results = $client->search('products', $search);
Handling Responses
Use Response objects for metadata (e.g., pagination, warnings):
$response = $client->search('products', $search);
$totalPages = $response->getTotalPages();
Bulk Operations
$bulkOperation = new \Commercetools\Client\BulkOperation();
$bulkOperation->addAction('products', '123', 'setPrice', ['value' => ['centAmount' => 1000]]);
$results = $client->executeBulk($bulkOperation);
Laravel Service Container Bind the client to the container for dependency injection:
$this->app->singleton('commercetools.client', function ($app) {
return ClientBuilder::withClientCredentialsFlow(
$app['config']['commercetools.client_id'],
$app['config']['commercetools.client_secret'],
$app['config']['commercetools.token_url']
)->withProjectKey($app['config']['commercetools.project_key'])
->withHttpClient(new GuzzleHttpClient())
->build();
});
Middleware for Auth
Extend the ClientBuilder to add custom middleware (e.g., logging):
$clientBuilder->withMiddleware(function ($request, $next) {
$request->getHeaders()->add('X-Custom-Header', 'value');
return $next($request);
});
Model Validation
Use Validation helpers for request payloads:
use Commercetools\Client\Validation\Validation;
$errors = Validation::validateProduct($productData);
if (!empty($errors)) {
throw new \InvalidArgumentException(implode(', ', $errors));
}
Deprecation Warning
Token Management
401 Unauthorized errors by refreshing the client:
try {
$client->getById('products', $id);
} catch (\Commercetools\Client\Exception\UnauthorizedException $e) {
$client->refreshToken();
retry logic...
}
Pagination Quirks
Response::getTotalPages() and Response::getTotalResults() to avoid missing data:
$page = 1;
do {
$results = $client->search('products', $search->withPage($page));
$page++;
} while ($page <= $response->getTotalPages());
Case Sensitivity
projectKey) are case-sensitive in requests. Ensure consistency:
$client->withProjectKey(strtoupper(env('CT_PROJECT_KEY'))); // if needed
Cache Invalidation
CacheMiddleware) does not auto-invalidate. Clear it manually after writes:
$client->getCache()->clear();
Enable Verbose Logging Add a middleware to log requests/responses:
$clientBuilder->withMiddleware(function ($request, $next) {
\Log::debug('Request:', [
'url' => (string) $request->getUri(),
'method' => $request->getMethod(),
'headers' => $request->getHeaders(),
'body' => $request->getBody(),
]);
$response = $next($request);
\Log::debug('Response:', [
'status' => $response->getStatusCode(),
'body' => (string) $response->getBody(),
]);
return $response;
});
Validate API Responses
Use Response::isSuccessful() to check for errors:
$response = $client->search('products', $search);
if (!$response->isSuccessful()) {
throw new \RuntimeException('API Error: ' . $response->getReasonPhrase());
}
Handle Rate Limits
Implement exponential backoff for 429 Too Many Requests:
use Symfony\Component\Stopwatch\Stopwatch;
$stopwatch = new Stopwatch();
$event = $stopwatch->start('api_call');
try {
$response = $client->getById('products', $id);
} catch (\Commercetools\Client\Exception\TooManyRequestsException $e) {
$retryAfter = $e->getRetryAfter();
$event->stop();
sleep($retryAfter);
$event->start('retry');
$response = $client->getById('products', $id);
}
Custom Models
Extend base models (e.g., Product) to add business logic:
class CustomProduct extends \Commercetools\Client\Model\Product
{
public function getFormattedPrice()
{
return '$' . ($this->getPrice()->getValue()->getCentAmount() / 100);
}
}
Event Subscriptions
Use the Eventing module to listen for Composable Commerce events:
$client->getEventing()->subscribe('OrderCreated', function ($event) {
\Log::info('New order:', $event->getPayload());
});
Custom HTTP Clients
Replace the default GuzzleHttpClient with a custom implementation (e.g., for signing requests):
$clientBuilder->withHttpClient(new class extends \Commercetools\Client\Http\HttpClient {
public function send(RequestInterface $request)
{
// Custom logic (e.g., add signature)
return parent::send($request);
}
});
How can I help you explore Laravel packages today?