Wednesday, October 28, 2015

An Actual Guide to Accessing Google Datastore in PHP!

You've scoured the Internet, you've asked your friends, and you've complained about it for ages. Now, prepared to be stunned!

First off, let's give a quick run down of what Google Datastore (henceforth abbreviated as GDS) actually is. Google D... I mean GDS... is a SQL-ish database. It works very similarly, but there are a few key differences.

First, let's draw some parallels between the two. First off, GDS doesn't have databases. Instead, it has "namespaces", the default of which has no name. This can be useful to partition different applications within the same project. Next, GDS will not have tables, instead it will have "kinds" of  "objects". Objects are analogous to rows. Because each instance of an object can have or not have certain properties, it's more a object than a row. This guide assumes you understand all of these concepts. If you don't, I suggest glancing at the overview found at the Google Developer Site.

Now for the interesting stuff. How to actually use this. I use a great project that I found called "PHP-GDS" which is an adapter library to work with the Google API Client for PHP. The newest version at the time of this writing, 2.0 Beta, is leaps and bounds over the previous 1.x generation of the library. It uses Protocol Buffers to work with the datastore faster and more efficiently than before. The webpage says it isn't ready for production use, but quite frankly I've had fewer problems with version 2 with ProtoBuf than I did with the standard API use in 1.x versions.

Let's walk through how to configure PHP-GDS step by step.

Step One: Install the Libraries

If you haven't already, you actually need the files to get this to work. I'm not going to explain how to do that here because every setup is different, but get the libraries (linked above) and install them.

Step Two: Write a Datastore Library

While this step isn't required, I sure found it useful. At least make sure you write a preface file and require_once() it at the beginning of each file you use. I also put convenience fetch and upsert methods into this file. I'll write this assuming you're going to write said convenience methods in this file. First, we'll include all of the files required to run the datastore. Change the paths to where these files are actually located.
require_once("Google/autoload.php");

require_once("GDS/Entity.php");
require_once("GDS/Gateway.php");
require_once("GDS/Mapper.php");
require_once("GDS/Schema.php");
require_once("GDS/Store.php");

require_once("GDS/Gateway/ProtoBuf.php");
require_once("GDS/Mapper/ProtoBuf.php");
Now that all of the dependencies are loaded, we can tell PHP-GDS about our project. Among the things we need, we need to tell it what our Project ID is, what our service account is, and what our namespace is. To find the Project ID, you just look at the Google Cloud Console. It's plastered everywhere. At the time of writing, the console is set up so that you can just look at the top left corner of the home screen and it'll show it.



Next thing you'll need is a service account (a Google account that belongs to an automated service, not a human.) Your project may already have one. If not, it's easy to create one. Go to "Credentials" under "APIs & auth"


Once you have these items, you can define the constants that will tell PHP-GDS about your project.
//define GDS constants
define('GDS_APP_NAME', 'app-name'); //Name of the app
define('GDS_SERVICE_ACCOUNT_NAME', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@developer.gserviceaccount.com'); //Google service account
define('GDS_DATASET_ID', 's~app-name'); //Name of the app prepended by "s~"
Now we're going to set up some basic object definitions. Even though GDS is technically schemaless, don't be that guy. We're going to define a schema because, quite frankly, I'm not sure how to use the library without one, but it can be done. You simply chain calls together to form the schema:
$schema = (new GDS\Schema('user')) //define the user
   ->addString("stringfield") //add a string
   ->addInteger(7) //an integer
   ->addDatetime(new DateTime()) //a datetime
   ->addFloat(10.4) //a floating point number
   ->addBoolean(TRUE) //a bit
   ->addStringList("friends") //a list of strings
   ->addString("notindexed",FALSE); //Pass false as the second argument if the field shouldn't be indexed.
Keep in mind that indexing fields will make them available in equality WHERE clauses. If you want inequalities, you have to define a index.yaml file in which you specify an order.

Next, you need to set up a gateway and the object stores. These are how PHP-GDS transacts with the datastore. These are really simple to do:
//Gateway requires a Google_Client and Dataset ID
$obj_gateway = new GDS\Gateway\ProtoBuf(GDS_DATASET_ID);
//Create the stores for their respective datatypes
$obj_object_store = new GDS\Store($schema,$obj_gateway);
Now you can use the $obj_schema_store to interact with the datastore on this specific type. To put an object into the datastore,
$obj_object = new GDS\Entity();
$obj_object->field = //Put something into the object
//Put more things in as you need to
$obj_object_store->upsert($obj_object);
Next, to query the datastore, you can send a GQL query like this:
$obj_object = $obj_object_store->fetchOne("GQL Query Goes Here"); //This will just get one. To return multiple, use fetchAll. Check the documentation of PHP-GDS
You can then mutate the object and upsert it back to the GDS to update an object. Keeping it in object form will keep it's identity so it won't create a new object in the datastore.

That's pretty much the gist of it. This is the basic How-To of how to get set up and running to using this great product. This library and this database system is fantastic, and I suggest you take a look at it because it truly is awesome.

Comment below if you think I missed anything or if you find an error in my code. I copy and pasted most of this from projects of mine that work, but then I went and modified it here to generalize it for everyone, so it may have broken. If you need any help, feel free to comment as well.

No comments:

Post a Comment