PHP on Google App Engine

Roadmap of talk

  • What is App Engine and the Google Cloud Platform?
  • Getting started with PHP on App Engine
  • Scaling your app and using asynchronous processing
    • demos featuring our brilliant startup app (sure to make millions)
    • a look at the code and App Engine admin console

Why the Cloud Platform for PHP?


App Engine


PHP on Google App Engine (Preview)

Open signups!

PHP on App Engine

App Engine APIs and Services

How do we start?


Getting Started:

The SDK Launcher and the 'guestbook' app

Common Apps on PHP App Engine

Migrating a typical app to App Engine


Google Cloud Storage (GCS)

  • Fast, scalable, distributed file system
  • GCS stream wrapper, + direct uploads via HTTP POST
$options = [ "gs" => [ "Content-Type" => "text/plain" ]];
$ctx = stream_context_create($options);
file_put_contents("gs://my_bucket/hello.txt", "Hello", 0, $ctx);

$fp = fopen("gs://my_bucket/some_file.txt", "w");
fwrite($fp, "Hello");

Configure your app to allow includes from GCS (Twig, Smarty, etc.):
google_app_engine.allow_include_gs_buckets = "bucket1, bucket2"

Portion of WP app.yaml file

- url: /(.*\.(htm$|html$|css$|js$))
  static_files: wordpress/\1
  upload: wordpress/(.*\.(htm$|html$|css$|js$))
  application_readable: true
- url: /wp-admin/(.+)
  script: wordpress/wp-admin/\1
  secure: always
- url: /wp-cron.php
  script: wordpress/wp-cron.php
  login: admin
- url: /wp-(.+).php
  script: wordpress/wp-\1.php
- url: /(.+)?/?
  script: wordpress/index.php 

Detour: An App Engine App's Admins


app.yaml for a Laravel app

application: your-app-id
version: one
runtime: php
api_version: 1


- url: /favicon\.ico
  static_files: public/favicon.ico
  upload: public/favicon\.ico

- url: /assets/(.*\.(htm$|html$|css$|js$|png$))
  static_files: public/assets/\1
  upload: public/assets/(.*\.(htm$|html$|css$|js$|png$))
  application_readable: true

- url: /.*
  script: public/index.php       

Introducing my brilliant startup idea...


App Engine Task Queues

  • Define tasks and process them asynchronously, in the background
  • App Engine automatically scales processing capacity
    • matches your queue configuration and processing volume.

Task Queues


Adding A Task to a Queue

Tasks are units of work to be performed by the app.
Task objects contain a request handler URL and an optional payload.

require_once 'google/appengine/api/taskqueue/PushTask.php';
use \google\appengine\api\taskqueue\PushTask;
$task_params = ['feed_url' => $feed_url, 'user_id' => $user_id];
$task = new PushTask('/do_add_feed_task', $task_params);

A Task Handler

require_once 'google/appengine/api/taskqueue/PushTask.php';
use \google\appengine\api\taskqueue\PushTask;
$task_params = ['feed_url' => $feed_url, 'user_id' => $user_id];
$task = new PushTask('/do_add_feed_task', $task_params);

The /do_add_feed_task handler script:

$user_id = $_POST['user_id'];
$feed_url = $_POST['feed_url'];
// in the handler, add the feed based on the task params
if (!addNewFeed($feed_url, $user_id)) {
  // ....

Define the handler in your app.yaml file

- url: /do_add_feed_task
  script: do_add_feed_task.php
  login: admin   
  • Task handlers are always run as 'admin'
  • You can use regexps in your app.yaml file, e.g.
- url: /(.+)_task
  script: /\1_task.php
  login: admin

Scheduling Tasks

  $task_options = [
    'delay_seconds' => $task_delay_seconds,

  $task = new PushTask('/rss_poll_handler',
    ['feed_url' => $feed_url],

Using Multiple Queues

- name: rss-poll
  rate: 50/s
- name: add-feed
  rate: 10/s
require_once 'google/appengine/api/taskqueue/PushTask.php';
use \google\appengine\api\taskqueue\PushTask;
$task = new PushTask('/rss_poll_handler',
  ['feed_url' => $feed_url], $task_options)->add('rss-poll');

Back to the app:

The development server

and the admin console

The App Engine SDK and Launcher

The Admin Console Dashboard

Admin Console Task Queues (first try)


But, feeds get updated at very different rates...

Let's define more task queues

- name: demo-fast-rss-poll
  rate: 70/s
  max_concurrent_requests: 25

- name: demo-medium-rss-poll
  rate: 50/s
  max_concurrent_requests: 25

... And schedule next feed poll according to the results returned, then pick queue based on that delay.

// Choose a queue to enqueue to based on the time the task will run.
 foreach($task_delay_to_queue_name_map as $delay => $name) {
   if ($task_delay_seconds < $delay) {
     $queue_name = $name;

The Admin Console Dashboard (second iteration)

Admin Console Task Queues (second iteration)

Summary: Scalable PHP apps on App Engine

  • Task Queue background processing is decoupled from request/response cycle
    • scheduling, execution and retries handled automatically
    • no management of queuing infrastructure
  • Your app autoscales with increased demand
  • Lets you focus on building the app.

Google Cloud Platform Starter Pack

Google Cloud Platform Starter Pack allows developers from affiliated partners to receive $2,000 of credit.

Apply at http://goo.gl/0YjkLQ.

Use promo code zend-con.


<Thank You!>