Migrating Google Cloud Clients to the New Surface

Document Summary

  • Google Cloud PHP Client Libraries are releasing new major versions (v2) to introduce new surface changes.
  • The PHP Team at Google has developed a tool to automatically upgrade clients (see ClientUpgradeFixer).

WHAT are the new Cloud Clients?

The new Cloud Clients are in the namespace \Client\, whereas the previous clients are one directory above with the same name. For example:

// This is the "new" client
use Google\Cloud\Retail\V2\Client\SearchServiceClient;

// This is the deprecated client (marked with @deprecated)
use Google\Cloud\Retail\V2\SearchServiceClient;

The main difference is that RPC methods which used to take a varying number of required arguments plus an array of optional arguments, now only take a single Request object:

// Create a client.
$searchServiceClient = new SearchServiceClient();

// Prepare the request message.
$request = (new SearchRequest())
    ->setPlacement($placement)
    ->setVisitorId($visitorId);

// Call the API and handle any network failures.
try {
    /** @var PagedListResponse $response */
    $response = $searchServiceClient->search($request);

    /** @var SearchResult $element */
    foreach ($response as $element) {
        printf('Element data: %s' . PHP_EOL, $element->serializeToJsonString());
    }
} catch (ApiException $ex) {
    printf('Call failed with message: %s' . PHP_EOL, $ex->getMessage());
}

RPCs use CallOptions

The new surface RPC methods take an optional array of CallOptions as the second argument. These are similar to how the $optionalArgs were used in the previous surface, but the new CallOptions only contain options for the call itself, whereas the previous $optionalArgs also held the optional fields for the request body:

// To set call-time options, such as headers, timeouts, and retry options,
// pass them in as the second argument
$callOptions = ['timeoutMillis' => 20];
$response = $searchServiceClient->search($request, $callOptions);

Requests have static ::build methods

Using Request objects directly can make it more difficult to quickly draft out the necessary code to deliver an RPC. To mitigate this friction, a static ::build method is now generated when one or more method signature annotations exist on the RPC.

Any request which has recommended parameters defined in its proto will include a ::build method, so that these parameters are easily discoverable:

// Create the RPC request using the static "::build" method
$request = ListOSPolicyAssignmentsRequest::build($parent);
$response = $searchServiceClient->search($request);

HOW should I upgrade?

The changes are mostly straightforward, and at a minimum require the following:

  • Update Google Cloud clients to use the new client namespace by appending \Client to the existing namespace.
  • Update RPC calls to accept the corresponding Request object.

NOTE: Client streaming calls do not require a Request object.

Automatically upgrade code using the ClientUpgradeFixer tool

To help migrate code to the new client surface, we've written a ClientUpgradeFixer to scan code and upgrade it to match the new client surface. This tool is not guaranteed to work, so be sure to test everything that it changes thoroughly. Read more about how to install and run the tool in its README.

The ClientUpgradeFixer uses PHP Coding Standards Fixer to upgrade code to use the new client surface:

# run the CS fixer for that directory using the config above
vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.google.php --dry-run --diff /path/to/my/project

This will output a diff of the changes. Remove --dry-run from the above command to apply the changes automatically.

-use Google\Cloud\Dlp\V2\DlpServiceClient;
+use Google\Cloud\Dlp\V2\Client\DlpServiceClient;
+use Google\Cloud\Dlp\V2\CreateDlpJobRequest;
 use Google\Cloud\Dlp\V2\InspectConfig;
 use Google\Cloud\Dlp\V2\InspectJobConfig;
 use Google\Cloud\Dlp\V2\Likelihood;
+use Google\Cloud\Dlp\V2\ListInfoTypesRequest;
 use Google\Cloud\Dlp\V2\StorageConfig;

 // Instantiate a client.
 $dlp = new DlpServiceClient();

 // optional args array (variable)
-$infoTypes = $dlp->listInfoTypes($parent);
+$request = (new ListInfoTypesRequest());
+$infoTypes = $dlp->listInfoTypes($request);

 // optional args array (inline array)
-$job = $dlp->createDlpJob($parent, ['jobId' => 'abc', 'locationId' => 'def']);
+$request2 = (new CreateDlpJobRequest())
+    ->setParent($parent)
+    ->setJobId('abc')
+    ->setLocationId('def');
+$job = $dlp->createDlpJob($request2);

Feedback

Your feedback is important to us! Please continue to provide us with any thoughts and questions in the Issues section of this repository.