Version 41.0.0.20250220
of the PHP SDK represents a full rewrite of the SDK with a number of breaking changes, outlined in the following sections. When upgrading to this version or later versions, take note of the changes in the SDK, including client construction and parameter names. If necessary, you can use the legacy version of the SDK along with the latest version.
SDK versions 40.0.0.20250123
and earlier continue to function as expected, but you should plan to update your integration as soon as possible to ensure continued support.
The new Client
class has some breaking changes and is constructed in a slightly different way than the legacy version of the SDK.
Legacy | New | Additional information | |
---|---|---|---|
Environment | baseUrl | An enum for specifying the environment (Sandbox or Production). | |
accessToken | token | The access token used for authentication. | |
customUrl | baseUrl | The base URL for API requests. | |
numberOfRetries | maxRetries | The configuration used to control the number of retries. | |
additionalHeaders | headers | Additional headers can be set at individual methods. | |
httpCallback | Removed | This option has been removed. | |
userAgentDetail | Removed | This option has been removed. |
// LEGACY
use Square\Legacy\SquareClient as LegacySquareClient;
$client = new LegacySquareClient(
config: [
'accessToken' => getenv('SQUARE_ACCESS_TOKEN') ?? '',
'environment' => 'sandbox',
],
);
// NEW
use Square\Environments;
use Square\SquareClient;
$client = new SquareClient(
token: getenv('SQUARE_ACCESS_TOKEN') ?? '',
options: [
'baseUrl' => Environments::Sandbox->value,
],
);
While the new SDK has many improvements, we understand that it takes time to upgrade when there are breaking changes. To make the migration easier, the new SDK exports the legacy SDK as Square/Legacy
. The following example shows how to use the new and legacy SDKs inside a single file:
<?php
use Square\Environments;
use Square\Legacy\SquareClient as LegacySquareClient;
use Square\Legacy\Models\CreateOrderRequest;
use Square\SquareClient;
use Square\Locations\Requests\GetLocationsRequest;
$legacyClient = new LegacySquareClient([
'accessToken' => getenv('SQUARE_ACCESS_TOKEN') ?? '',
'environment' => 'sandbox',
]);
$client = new SquareClient(
token: getenv('SQUARE_ACCESS_TOKEN') ?? '',
options: [
'baseUrl' => Environments::Sandbox->value,
],
);
function getLocation($client) {
$response = $client->locations->get(
new GetLocationsRequest([
'locationId' => 'YOUR_LOCATION_ID',
]),
);
return $response->getLocation();
}
function createOrder($legacyClient, $location) {
$order = new Order($location['id']);
$request = new CreateOrderRequest;
$request->setIdempotencyKey(uniqid());
$request->setOrder($order);
return $legacyClient->getOrdersApi()->createOrder($request);
}
$location = getLocation($client);
$result = createOrder($legacyClient, $location);
You should migrate to the new SDK using the following steps:
- Upgrade the square/square package to
^41.0.0.20250220
. - Search and replace all requires and imports from
Square
toSquare\Legacy
. - Gradually introduce methods from the new SDK by importing them from the
Square
import.
The previous version of the SDK relied on using a mix of builders and setter methods, which created verbose integrations. For example, consider the following createOrder
method call:
// LEGACY
$order = new Order($location['id']);
$request = new CreateOrderRequest;
$request->setIdempotencyKey(uniqid());
$request->setOrder($order);
$legacyClient->getOrdersApi()->createOrder($request);
In the new SDK, you can consolidate all the parameters in a single statement. All the parameters are still specified by their name, which makes their meaning instantly clear.
// NEW
$client->orders->create(
new CreateOrderRequest([
'idempotencyKey' => uniquid(),
'order' => new Order([
'locationId' => $location['id'],
]),
]),
)
This SDK leverages the PHP 8.1 first-class enums to improve type safety and usability. To maintain forward compatibility with the API (where new enum values might be introduced in the future), enum properties are defined as string
and use value-of
annotations to specify the corresponding enum type.
The best example of this is when the client's base URL or environment is configured.
// LEGACY
use Square\Legacy\SquareClient as LegacySquareClient;
$client = new LegacySquareClient(
config: [
'environment' => 'sandbox',
],
);
// NEW
use Square\Environments;
use Square\SquareClient;
$client = new SquareClient(
options: [
'baseUrl' => Environments::Sandbox->value, // Enums can be accessed with '->value'.
],
);
Previously, API classes were named after the resource you're interacting with and suffixed with Api
. To interact with customer resources, you used the client->getCustomersApi()
method.
The method was named based on the action you want to perform and the same resource name specified earlier. To list customers, you call client->getCustomersApi()->listCustomers
.
// LEGACY
$client->getCustomersApi()->listCustomers();
The new API classes are named after the resource without the Api
suffix and their methods are named after the action without repeating the resource name.
// NEW
$client->customers->list();
When interacting with a nested resource, you can chain the resources using the arrow-notation.
// NEW
$client->customers->groups->list();
Other class and method names might have changed. The differences are easiest to discover by exploring the new method signatures.
The Square paginated endpoints now support auto-pagination with an iterator. Callers don’t need to manually fetch the next page. You can now iterate over the entire list and the client automatically fetches the next page behind the scenes. The following example shows the same code, with the legacy and new SDK:
// LEGACY
$limit = 10;
$listCustomersResponse = $legacyClient->getCustomersApi()->listCustomers(
limit: $limit,
sortField: 'DEFAULT',
sortOrder: 'DESC'
);
while (!empty($listCustomersResponse->getCustomers())) {
$customers = $listCustomersResponse->getCustomers();
foreach ($customers as $customer) {
echo sprintf(
"customer: ID: %s Version: %s, Given name: %s, Family name: %s\n",
$customer->getId(),
$customer->getVersion(),
$customer->getGivenName(),
$customer->getFamilyName()
);
}
$cursor = $listCustomersResponse->getCursor();
if ($cursor) {
$listCustomersResponse = $legacyClient->getCustomersApi()->listCustomers(
cursor: $cursor,
limit: $limit,
sortField: 'DEFAULT',
sortOrder: 'DESC'
);
} else {
break;
}
}
// NEW
$customers = $client->customers->list(
new ListCustomersRequest([
'limit' => 10,
'sortField' => 'DEFAULT',
'sortOrder' => 'DESC'
]),
]);
foreach ($customers as $customer) {
echo sprintf(
"customer: ID: %s Version: %s, Given name: %s, Family name: %s\n",
$customer->getId(),
$customer->getVersion(),
$customer->getGivenName(),
$customer->getFamilyName()
);
}
If you need to paginate page by page, you can still do so with a lot less code:
- Use
$customers->getPages()
to iterate over each page individually. - Use
$customers->getItems()
to get the customers of the current page.
$customers = $client->customers->list(
new ListCustomersRequest([
'limit' => 10,
'sortField' => 'DEFAULT',
'sortOrder' => 'DESC'
]),
]);
foreach ($customers->getPages() as $page) {
foreach($customer as $page->getItems()) {
echo sprintf(
"customer: ID: %s Version: %s, Given name: %s, Family name: %s\n",
$customer->getId(),
$customer->getVersion(),
$customer->getGivenName(),
$customer->getFamilyName()
);
}
}
If you need to paginate page by page, you can still do so with a lot less code:
- Use
$customers.getPages()
to iterate over each page individually. - Use
$customers.getItems()
to get the customers of the current page.
$customers = $client->customers->list(
new ListCustomersRequest([
'limit' => 10,
'sortField' => 'DEFAULT',
'sortOrder' => 'DESC'
]),
]);
foreach ($customers->getPages() as $page) {
foreach($customer as $page->getItems()) {
echo sprintf(
"customer: ID: %s Version: %s, Given name: %s, Family name: %s\n",
$customer->getId(),
$customer->getVersion(),
$customer->getGivenName(),
$customer->getFamilyName()
);
}
}