Category Archives: tutorial

Making Cloud Datastore Easy For PHP on App Engine

Firstly, thank you to @slangley and the team for asking me to guest post here. I really hope this helps you PHP folks on App Engine.

TL;DR – I can has code?

Sure, no problem. https://github.com/tomwalder/php-gds

Introduction

PHP on Google App Engine went Generally Available earlier this year, and that’s pretty awesome.

Certainly for me (and probably some of you) it makes both prototyping and running super-scalable web applications really easy and reliable.

Whilst the PHP part of the App Engine environment is ultra easy to use and scalable, you are likely to need a similarly featured data persistence layer for any useful applications. MySQL is cool and all, but it costs money (via Cloud SQL) and can’t scale automatically in the same way App Engine can.

Enter Cloud Datastore.

It’s pretty sweet – auto-scaling, distributed, supports transactions, mostly schema-less, managed, free to get started (up to 1GB of data and 50k queries per day).

So, you ask yourself, how do I use this amazing thing? Well until not that long ago it was a bit of a pain. you needed loads of glue code to get even the basics running.

So the php-gds library was built to simplify usage of Datastore from PHP. It tries to make it really, really easy to get started, whilst also being feature rich. It’s seeing a fair amount of adoption as far as I can tell, and the guys at Google are pretty keen on it too – hence this post!

Example – Write to Datastore

For any code running on the local development server or on a real App Engine application, it’s this easy…

// Build a new entity
$obj_book = new GDS\Entity();
$obj_book->title = 'Romeo and Juliet';
$obj_book->author = 'William Shakespeare';
$obj_book->isbn = '1840224339';

// Write it to Datastore
$obj_store = new GDS\Store('Book');
$obj_store->upsert($obj_book);

Example – Read from Datastore

Again, I try to make reading data is simple and intuitive as possible…

$obj_store = new GDS\Store('Book');
foreach($obj_store->fetchAll() as $obj_book) {
    echo "Title: {$obj_book->title}, ISBN: {$obj_book->isbn} <br />", PHP_EOL;
}

Native Access or JSON API

The php-gds library uses the native, Protocol Buffer APIs to access the Datastore – this means it is super fast.

It also supports remote access using the JSON API – in fact, you can use the same code against both, just passing the right Gateway object into your Store. More details on GitHub here.

Query Language – GQL

At the time of writing, php-gds uses the GQL, which is very similar to SQL, to query Datastore – and parameter binding, which is recommended.

$obj_book_store->fetchOne("SELECT * FROM Book WHERE isbn = @isbnNumber", [
    'isbnNumber' => '1853260304'
]);

Best Practice – Define a Schema/Model

You will get more (for less) if you define your Schema clearly, including what fields in your data to index. Indexing costs money (above the free quota) so it’s a good move to think about and define your model

More detail on defining a model can be found here.

Further Reading

There is a pretty decent set of guidance in the GitHub README and in the examples.

Support

Create an issue on GitHub or post on SO.

About Me

My name is Tom Walder, I’m CTO at Docnet, an e-commerce platform and solutions provider based in Manchester, UK. You can find me on twitter @tom_walder

I am the author of the php-gds Datastore library for PHP.

Direct File Uploads for PHP 5.5

One of the new features we announced in the 1.9.18 App Engine release is the ability to upload files directly to you application, without the need to upload the files to Google Cloud Storage first.

Direct uploads leverages the same in memory virtual filesystem that is used to provide temporary filesystem support. Direct uploads are only available with the PHP 5.5 runtime and are also limited to a maximum combined size of 32MB, which is the incoming request size limit.

Direct Upload Example

Following is a small sample application that demonstrates direct file uploads. This sample application:

  • Uses HTML5 multiple file upload support to upload image files.
  • Saves the original uploaded file into Google Cloud Storage.
  • Creates a greyscale version of the uploaded image and writes that to Google Cloud Storage.
  • Uses the image serving API to create links to serve the stored images at original size.
  • Also uses the image serving API to create thumbnail links of the images, without the application having to create the thumbnails.
  • Finally, displays a simple page with the thunbnailed links to the saved files.

For this application we’ll create 3 source files.

app.yaml

The app.yaml file has the following contents. Note that the runtime is php55.

application: php-uploads
version: 1
runtime: php55
api_version: 1
threadsafe: true

handlers:
- url: /handle_upload
  script: handle_upload.php

- url: .*
  script: direct_upload.php

direct_upload.php

This file presents a form for the user to upload multiple files to your application. As direct uploads are only in PHP 55 it checks that as well.

<?php
// Direct uploads requires PHP 5.5 on App Engine.
if (strncmp("5.5", phpversion(), strlen("5.5")) != 0) {
  die("Direct uploads require the PHP 5.5 runtime. Your runtime: " . phpversion());
}
?>
<html>
<body>
<form action="handle_upload" method="post" enctype="multipart/form-data">
  Send these files:<p/>
  <input name="userfile[]" type="file" multiple="multiple"/><p/>
  <input type="submit" value="Send files" />
</form>
</body>
</html>

handle_upload.php

The handle_upload script does the heavy lifting of creating the greyscale images, saving them in Cloud Storage and displaying the results. If you were doing this in a production app you’d need a lot more error handling, but I’ve left it out for brevity.

<?php

use google\appengine\api\cloud_storage\CloudStorageTools;

$bucket = CloudStorageTools::getDefaultGoogleStorageBucketName();
$root_path = 'gs://' . $bucket . '/' . $_SERVER["REQUEST_ID_HASH"] . '/';

$public_urls = [];
foreach($_FILES['userfile']['name'] as $idx => $name) {
  if ($_FILES['userfile']['type'][$idx] === 'image/jpeg') {
    $im = imagecreatefromjpeg($_FILES['userfile']['tmp_name'][$idx]);
    imagefilter($im, IMG_FILTER_GRAYSCALE);
    $grayscale = $root_path .  'gray/' . $name;
    imagejpeg($im, $grayscale);

    $original = $root_path . 'original/' . $name;
    move_uploaded_file($_FILES['userfile']['tmp_name'][$idx], $original);

    $public_urls[] = [
        'name' => $name,
        'original' => CloudStorageTools::getImageServingUrl($original),
        'original_thumb' => CloudStorageTools::getImageServingUrl($original, ['size' => 75]),
        'grayscale' => CloudStorageTools::getImageServingUrl($grayscale),
        'grayscale_thumb' => CloudStorageTools::getImageServingUrl($grayscale, ['size' => 75]),
    ];
  } 
}

?>
<html>
<body>
<?php
foreach($public_urls as $urls) {
  echo '<a href="' . $urls['original'] .'"><IMG src="' . $urls['original_thumb'] .'"></a> ';
  echo '<a href="' . $urls['grayscale'] .'"><IMG src="' . $urls['grayscale_thumb'] .'"></a>';
  echo '<p>';
}
?>
<p>
<a href="/">Upload More</a>
</body>
</html>

If you stumble across any problems, please let us know on either stack overflow or by creating an issue in our tracker.

Using the WordPress Importer From the App Engine Plugin

As we announced recently, the new version of our App Engine WordPress Plugin includes import support for WordPress export files, forked from the popular WordPress importer plugin.
This plugin lets you take content that you’ve exported from another WordPress site, in the form of an .xml file, and import it into your App Engine WordPress site.

This post walks through the process of doing such an import. It assumes that you already have a WordPress installation on App Engine— if not, see these instructions.

If you will be doing an import of a large .xml file, see the section below on “What to Do if You Have a Large Import“.  As described in that section, you should make a temporary configuration change to your app before you do the import, to ensure that it finishes successfully.

Continue reading

PHP App Engine Apps and File System Concepts

If you’re new to App Engine, then the file system model may be a bit different from what you might have experienced using other hosts.

With an App Engine application, you cannot write to the file-system where your application is deployed. Your application can read any files from the deployed directory structure, but it can’t write to that file-system. Instead, the application can use Google Cloud Storage (GCS) for both reading and writing files.
To convert an app to use GCS for writable files, here are the primary things that you will typically need to do:

Another implication of the read-only file system is that if your app has a ‘plugin’ model, like WordPress, you can’t install or update plugins from your deployed app. Instead, you will need to install or update any plugins locally, then redeploy the app.

You can find lots more info on all of the following in the documentation for the PHP runtime.

Continue reading

Generating Dynamic WordPress sitemaps on App Engine

Sitemaps are a valuable tool in helping search engines crawl your website. In this post I’ll show you how you can have a dynamically generated sitemap for a WordPress blog hosted on Google App Engine.

Because of the read-only nature of the file system on App Engine, we’ll use Google Cloud Storage to store the generated sitemap file. We’ll also add some handlers to serve the sitemap, and to update it as part of a scheduled cron job.

Continue reading

Getting started with the Cloud Datastore on PHP App Engine, Part II

Introduction

This is the second in a series of posts on using the Google Cloud Datastore on PHP App Engine.
The code for the examples in this post is here: https://github.com/amygdala/appengine_php_datastore_example.

The previous post walked through the process of setting up your PHP App Engine app to connect with the Datastore, using the Google API client libraries.
It demonstrated how to create a test Datastore entity, and showed how to set up a “Datastore service” instance, using a DatastoreService class, to make it easier to send requests.

However, using the API client libraries, there is a fair bit of overhead in composing requests to the Datastore and processing the responses, and mapping entities to instances of classes in your app. So, in this post, we’ll define some classes to make it easier to create, update, and fetch Datastore entities.
We’ll define a `Model` base class, then show an example of subclassing it to map to a specific Datastore Kind.

Continue reading

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.

Continue reading

Getting started with Laravel on PHP for App Engine

Introduction

This article walks through the process of deploying a Laravel 4 app to the App Engine PHP runtime.

Laravel is a web application framework that supports common tasks used in the majority of web projects, such as authentication, routing, sessions, and caching.

The Laravel 4 Starter Kit developed by Bruno Gaspar demos a simple blog application, and is a nice example of how to use the Laravel framework itself, as well as some of its packages. It should get you started on how to define and deploy your own app. If you’re not familiar with Laravel, you will find it useful to look over its documentation as well.

We’ll look at how to deploy this ‘starter kit’ app to App Engine.

Thanks and credit to Gilles Mergoil, who authored this blog post on running Laravel on a previous release of App Engine.

Continue reading

Using the Google APIs Client Library for PHP with App Engine

Important Note: Newer releases of the Google APIs client have support for App Engine out of the box, making this article obsolete.

Download the latest version from the github repository.

The Google API Client library allows you to work with Google APIs such as Analytics, Adsense, Google+, Calendar, Drive or Games easily from your application. Recent versions of the client library include support for HTTP streams, which makes it simple to use the library from an App Engine application just by tweaking the configuration file.

Follow these steps to get the client library up and running.

  1. Download the latest release package of the client.
  2. Extract the library from the archive and copy the google-api-php-client directory to your project root.
  3. Edit the file google-api-php-client/src/config.php, and configure the client to use HTTP streams and memcache by making the following changes to the $apiConfig array.
        // Which Authentication, Storage and HTTP IO classes to use.
        'authClass'    => 'Google_OAuth2',
        'ioClass'      => 'Google_HttpStreamIO',
        'cacheClass'   => 'Google_MemcacheCache',
    
        // We need to configure fake values for memcache to work
        'ioMemCacheCache_host' => 'does_not_matter',
        'ioMemCacheCache_port' => '37337',
    
  4. Test that the client is working correctly by following the Google Plus example on the client home page.

Note that to use the API client from your application, you’ll need to follow the instructions for using OAuth 2.0 with your application.

In a follow-up post we’ll show you how to use the Google API client to access the Google Cloud Datastore from your application.