Getting Started with the Cloud Datastore on PHP App Engine

Introduction

In this post, we’ll show how to access the Google Cloud Datastore from a PHP App Engine app.

This is the first in a series of posts on using the Cloud Datastore on PHP App Engine.
The code for the examples in this post is here: https://github.com/amygdala/appengine_php_datastore_example. (Some of the files in this repo won’t be mentioned in this post, but will be referenced in the post that follows this one).

PHP on Google App Engine supports several alternatives as for a persistent store. One is the Cloud Datastore, a distributed, robust, fully managed, schemaless database, which supports transactions and scales automatically.
(If you have built App Engine apps for other runtimes, this is the same Datastore that you’ve used before; it now supports an HTTP interface as well).
This article assumes that you already have a basic familiarity with Datastore concepts.

There is not yet a native Datastore API for PHP on app engine. So, instead we’ll show how to use the Cloud Datastore API to connect to the Datastore from your PHP app.
First, we’ll show how to configure your app and associated Cloud Project so that your app will be able to connect to the Datastore.

Then, we’ll look at how to use the Google API client libraries as a basis for authenticating with the Datastore, sending requests, and receiving responses, and we’ll build a DatastoreService class to make connecting a bit easier.

Setting Up Your App Engine App to Talk to the Cloud Datastore

In this article, we assume you’ve already registered an App Engine app application, and are familiar with the basics of creating and deploying a PHP App Engine project.
If not, you can get more information here.

Then, download this little example project, which includes the code used in this post. Edit the app.yaml file to use your app id.

The first step in using the Cloud Datastore is to activate the Cloud Datastore service, and set up your App Engine app to connect to the Google Cloud Datastore.
Follow the instructions for setting up access to an existing App Engine datastore, using your app id. This will result in the generation of a service account email address, and a downloaded private key.

Note the service account address, and move the private key file to the root directory of your App Engine app’s project.

We’ll need to provide this config information to the API Client libraries, to set up access to the Datastore service. Define an array with the following information, and put it in a config.py file, using the service account address and private key file that you just generated, and replacing ‘xxx’ with your values. This example assumes that the private key file is in the same directory as the config file. We’ll make use of this config information shortly.

$google_api_config = [
  'application-id' => 'A name for your app engine app',
  'service-account-name' => 'xxx@developer.gserviceaccount.com',
  'private-key' => file_get_contents('xxx-privatekey.p12'),
  'dataset-id' => 'your-app-id'
];

Downloading and Installing the API Client Libraries

Our next step is to include the Google API Client Libraries in the App Engine’s app project. The API Client Libraries provide access to many Google APIs, and are supported for many languages.

For these examples, we’ll use the v1 alpha version of the PHP API client libraries. Download the code here: https://github.com/google/google-api-php-client. You can download the code as an archive, or if you have git installed, you can do the following from the command line:

git clone https://github.com/google/google-api-php-client.git .

You can also use Composer.

Once downloaded, copy <google-api-php-client>/src/Google to your App Engine project’s top-level directory.

Accessing the Datastore via the API Client Libraries

At this point, you’ve generated the credentials to connect to the Cloud Datastore via the API client libraries, and have installed the API client libraries to support requests to and responses from the Datastore service.

The datastore_connect.php handler script lets you test your configuration.

This handler script creates or updates a test entity— of kind “testkind”— in the Datastore. It will throw an exception if it can’t connect.
(Note that this code assumes that you’ve created a config.php file and installed the API Client Libraries as described above).

You can try this test handler either from the development server:

http://localhost:8080/datastore_connect

or from your deployed app:

http://<your-app-id>.appspot.com/datastore_connect

You should see the response “Connected!” when you hit the URL. If there was some issue connecting, you will see a message to “check the logs” instead. You can go to the App Engine Admin console for your app to see more information about the error. Once you’ve successfully connected, you can see your new test entity in the Admin console, in the Datastore Viewer panel!

A DatastoreService class

If you successfully connected using the test code above, you’re set up with the basics for writing an app that communicates with the Datastore.
But, we can do something to make the connection process easier: we’ll define a DatastoreService class, which we’ll use to instantiate a service object through which we’ll communicate to the Datastore.

The datastore_connect2.php handler script uses this class.

To create a datastore service object, pass the $google_api_config configuration array that you defined above— which holds information about your Cloud project credentials— to the DatastoreService constructor. Then, pass the returned instance to the DatastoreService::setInstance method.

require_once 'config.php';
require_once 'DatastoreService.php';
...
DatastoreService::setInstance(new DatastoreService($google_api_config));

Poking under the hood, the DatastoreService constructor calls an init method. Here, the credentials in the config array are used to build a Google_Auth_AssertionCredentials object, which in turn is used to request a Datastore service object via the Google Client API.

require_once 'Google/Client.php';
require_once 'Google/Auth/AssertionCredentials.php';
require_once 'Google/Service/Datastore.php';
...
  private function init($options) {
    foreach(self::$required_options as $required_option) {
      if (!array_key_exists($required_option, $options)) {
        throw new InvalidArgumentException(
          'Option ' . $required_option . ' must be supplied.');
      }
    }
    $client = new Google_Client();
    $client->setApplicationName($options['application-id']);
    $client->setAssertionCredentials(new Google_Auth_AssertionCredentials(
      $options['service-account-name'],
      self::$scopes,
      $options['private-key']));
    $service = new Google_Service_Datastore($client);

    $this->dataset = $service->datasets;
    $this->dataset_id = $options['dataset-id'];
  }

We can use the returned service object to issue our requests to the Datastore.

In addition, in DatastoreService, we can define some helper methods to make it easier to send requests.
As an example, here is the commit request helper, which expects to be passed a Google_Service_Datastore_CommitRequest object.

public function commit(Google_Service_Datastore_CommitRequest $postBody, $optParams = []) {
    return $this->dataset->commit($this->dataset_id, $postBody, $optParams);
  }

This simplifies our test code, where we can now do something like:

DatastoreService::setInstance(new DatastoreService($google_api_config));
$req = create_test_request();
DatastoreService::getInstance()->commit($req);

Summary

In this post, we’ve walked through the basics of setting up a PHP App Engine app to connect to the Cloud Datastore.

In our next two posts in this series, we’ll define some classes to make it easier to write code that creates and updates Datastore entities, and show a complete example app.
Update: here is Part II.

3 thoughts on “Getting Started with the Cloud Datastore on PHP App Engine

  1. Pingback: PHP App Engine Apps and File System Concepts | Tips and Tricks for PHP on Google App Engine

  2. leX

    Hi guys!

    I followed the tutorial and http://localhost:8080/datastore_connect worked like a charm. So I deployed the project an got this errors:

    Warning: file_get_contents(): Unsupported SSL context options are set. The following options are present, but have been ignored: cafile in /base/data/home/apps/???/1.373121324317797163/Google/IO/Stream.php on line 115 Warning: file_get_contents(): cannot represent a stream of type http via urlfetch as a File Descriptor in /base/data/home/apps/???/1.373121324317797163/Google/IO/Stream.php on line 115 Warning: file_get_contents(compress.zlib:/ /https://accounts.google.com/o/oauth2/token): failed to open stream: operation failed in /base/data/home/apps/???/1.373121324317797163/Google/IO/Stream.php on line 115 There was an issue — check the logs.

    I found nothing on the internet (and GAE logs) about this messages… Is there a possibility that Google changed the PHP runtime so that no more outgoing SSL connections are working? I know my PHP code is working everywhere, but not after a GAE deployment. I'm using version 1.0.1-alpha of the Google client API for PHP.

    Do you know something about that? Thanks!

    1. amyu Post author

      Hmmm… thanks for the report. We'll look into it and update here again (we may ask you for more info).

      Update: We've reproduced the issue, which is related to a recent update to the API client libs. Thanks for reporting. As a temporary workaround, try commenting out the following clause from IO/Stream.php at line 107:

      if (!$this->client->getClassConfig("Google_Http_Request", "disable_gzip")) {

      $url = self::ZLIB . $url;

      }

Comments are closed.