Corona SDK – Saving player score on server using PHP

tl;dr for the impatient, just download or clone this Github repository:

Corona SDK provides methods of sending data to a server via Lua sockets. It can use GET and POST
just as well, leaving it up to the developer to make the final decision. In addition to sending data,
retrieving the server generated response is convenient when it’s encoded in JSON format.

An example of a GET and POST request looks like this:

local query = "id=1&game=3&score=100"
local query2 = "id=1&game=2&score=100"
local serverUrl = ""

local getHTTP = serverUrl .. "?" .. query
-- GET request. There is no second body paramater
local body, code, headers = http.request( getHTTP )

-- POST example
local b, c, h = http.request( serverUrl, query2 )

If the server responds with a JSON format, just use json.decode()
on the response body:

local asJsonG = json.decode(body)

For the server side, we will use a simple PHP framework, accurately named Slim. Being a micro framework, it does just enough to get boilerplate code out of the way and allows us to define routes and handler functions as callables.
Example code presumes PHP >= 5.3 is used. We take advantage of anonymous functions and ‘use’ keyword for scope manipulation. In addition to the web framework, we use PHP Doctrine ORM as our database abstraction layer. It provides us with and object relation mapper and active record type system to access the database – MySQL in this instance.


  1. Check that your hosts file has the domain defined
  2. Check that Apache has the virtual host entry defined
  3. Check that there is a .htaccess file in the same directory as index.php file
  4. Check that the host name you chose and the host name inside the Corona application match
  5. Check that the credentials for the database inside bootstrap.php match
  6. Check that the database exists and necessary tables are present
  7. Check that you can load the test example at http://YOURDOMAIN/index.php
  8. Nice to have – use mod_rewrite to hide away the index.php from the URL

Request lifecycle
As soon as above Lua code is executed, an HTTP request is sent to the server. Slim PHP framework will parse the parameters and allow us to handle them according to application logic. First entry point in this example happens inside index.php, which simply loads the bootstrap.php file from the parent directory. The boostrap files and any other non publicly accessible files are hidden outside of the Apache document root for a reason. As soon as the application bootstrapping begins, we load the Slim framework, Doctrine, create a database connection and load our models.

//require framework files
require 'Slim/Slim.php';
require 'doctrine/lib/doctrine.php';
spl_autoload_register(array('Doctrine', 'autoload'));
$manager = Doctrine_Manager::getInstance();

//Le database and other goodies
$dsn = 'mysql:dbname=mygame;host=';
$dbuser = 'letme';
$dbpass = 'in';
$dbh = new PDO( $dsn, $dbuser, $dbpass );

$dbcon = Doctrine_Manager::connection($dbh);

$dbcon->setOption('username', $dbuser);
$dbcon->setOption('password', $dbpass);

$manager->setAttribute(Doctrine_Core::ATTR_AUTOLOAD_TABLE_CLASSES, true);


//Le web application
$app = new Slim();
$app->dbcon = $dbcon;

//URL paths and such
require 'routes.php';

//Le start

Models and database:
We have three tables in this sample application: user, score, game. We will allow one score per game, where game is treated more like a level inside a game. Table relations allow for a user to have one high score per game. Score table will hold the user id, game id and the high score. Game table holds ids and names of our levels and User will contain the
user id and name. Three PHP files are created by hand, to match this structure on Doctrine side. This will allow us to manipulate the tables using Doctrine object or query model. These three files are located inside the models directory.

Saving and retrieving data from database:
To retrieve data from database, point your application to http://YOURDOMAIN/index.php/testdb/ inside the browser. Slim framework will dispatch the matching callable, in this case the GET handler on line 11 inside routes.php. On line 16, we get all users using this piece of code $users = Doctrine_Core::getTable('User')->findAll(); Iterating over the result is as simple as using a foreach loop. On line 19, we can check of the User object has any scores associated to it: if( count($user->Scores) ), if so – we can loop over these and retrieve them further. This can be streamlined by using a leftJoin method, left out on purpose to show the relation flow between the tables.

PHP handler for Lua request:
On line 31, we have a Slim handler that will be dispatched when /savescore/ URL path is requested. It will answer to GET and POST request in the same way, because we used a generic route mapper $app->map('/savescore/' and defined the HTTP methods inside the ->via('GET', 'POST') section. Parameters are extracted from either type of request and passed on to function that handles saving the score using Doctrine object notation. In case of an exception, we return the unfiltered message back to Corona application.