Streams tutorial.

This commit is contained in:
Matt Butcher 2012-03-15 13:37:04 -05:00
parent 926d2f18d4
commit 89592860a7
3 changed files with 279 additions and 0 deletions

View File

@ -0,0 +1,41 @@
<?php
require_once __DIR__ . '/../src/HPCloud/Bootstrap.php';
use \HPCloud\Bootstrap;
Bootstrap::useAutoloader();
Bootstrap::useStreamWrappers();
$ini = parse_ini_file(getenv('HOME') . '/.hpcloud.ini');
$settings = array(
'account' => $ini['account'],
'key' => $ini['secret'],
'tenantid' => $ini['tenantId'],
'endpoint' => $ini['url'],
);
Bootstrap::setConfiguration($settings);
// Create a new file and write it to the object store.
$newfile = fopen('swift://Example/my_file.txt', 'w');
fwrite($newfile, "Good Morning!");
fclose($newfile);
// Check for an object:
if (file_exists('swift://Example/my_file.txt')) {
print "Found my_file.txt." . PHP_EOL;
}
// Get an entire object at once:
$file = file_get_contents('swift://Example/my_file.txt');
print 'File: ' . $file . PHP_EOL;
$cxt = stream_context_create(array(
'swift' => array(
'account' => $ini['account'],
'key' => $ini['secret'],
'tenantid' => $ini['tenantId'],
'endpoint' => $ini['url'],
),
));
print file_get_contents('swift://Example/my_file.txt', FALSE, $cxt);

238
doc/streams-tutorial.md Normal file
View File

@ -0,0 +1,238 @@
Tutorial: Using Stream Wrappers {#streams-tutorial}
===============================
This is an introduction to the HPCloud-PHP library. While the library is
large and feature-rich, this tutorial focuses on the Stream Wrapper
feature. (There is also a [tutorial about the object-oriented
library](@ref 00-tutorial).)
## TL;DR
With a few lines of setup code, you can fetch objects from HP Cloud's
object storage using built-in PHP functions like this:
~~~{.php}
<?php
// Create a new file and write it to the object store.
$newfile = fopen('swift://Example/my_file.txt', 'w');
fwrite($newfile, "Good Morning!");
fclose($newfile);
// Check for an object:
if (file_exists('swift://Example/my_file.txt')) {
print "Found my_file.txt." . PHP_EOL;
}
// Get an entire object at once:
$file = file_get_contents('swift://Example/my_file.txt');
print 'File: ' . $file . PHP_EOL;
?>
~~~
In fact, the vast majority of file and stream functions work with
HPCloud's `swift://` URLs.
The rest of this tutorial explains how they work.
## The Setup
The example above does not show the code necessary for initializing the
HPCloud stream wrapper. In this section, we will look at the necessary
setup code.
### Loading Classes
The HPCloud PHP library is structured following SPR-0 recommendations.
Practically speaking, what this means is that applications that use an
SPR-0 autoloader may be able to automatically load the HPCloud library.
However, we'll assume that that is not the case. We'll assume that the
library needs to be initialized manually.
What we will do is first load the HPCloud Bootstrap.php file, and then
use the autoloader in that file to load the rest of the library:
~~~{.php}
<?php
require_once '/HPCloud/Bootstrap.php';
use \HPCloud\Bootstrap;
Bootstrap::useAutoloader();
Bootstrap::useStreamWrappers();
?>
~~~
The first thing the example above does is require the Bootstrap.php
file, which contains code necessary for initializing the HPCloud
library.
Next, we call two static methods on the HPCloud::Bootstrap object:
- Bootstrap::useAutoLoader(): This tells HPCloud to load any other
classes on demand. Since we use this, we don't need any more `require`
or `include` statements.
- Bootstrap::useStreamWrappers(): This tells HPCloud to register its
stream wrapper classes.
In a nutshell, PHP allows libraries to map a particular URL pattern to a
stream wrapper. HPCloud registers the `swift://` URL prefix. So any
request to a URL beginning with `swift://` will be proxied through the
HPCloud library.
## Setting Up Authentication
When working with remote HPCloud Object Storage, you must authenticate
to the remote system. Authentication requires the following four pieces
of information:
- account: Your account ID
- key: Your account's secret key
- tenantid: The tenant ID for the services you wish to use
- endpoint: The endpoint URL for HPCloud's Identity Services. It usually
looks something like this: `https://region-a.geo-1.identity.hpcloudsvc.com:35357`
All four of these pieces of information can be found in the **API Keys**
section of your [management console](https://manage.hpcloud.com)
account.
(Note: You can use your username and password instead of account and
key, but you still must supply the tenant ID. Instead of supplying
`account` and `key`, use `username` and `password`.)
We are going to look at two ways to set authentication information. The
first is global. That means we supply it once, and all stream and file
functions automatically use that information. The second is to pass
authentication information into the stream context.
### Global Configuration
Supplying global account information has two distinct advantages:
-# It reduces the complexity of your code
-# It allows context-less functions like `file_exists` and `stat` to
work.
But it has a disadvantage: *Only one account can be used at a time.* Since
that account's information is shared across all stream wrappers, they
all share the same account, tenant Id, and service catalog.
If you are working on an application that needs to connect to more than
one account in the same request, you may find this setup imperfect for
your needs.
That said, here's how we set up a global configuration:
~~~{.php}
$settings = array(
'account' => YOUR_ACCOUNT_NUMBER,
'key' => YOUR_SECRET_KEY,
'tenantid' => YOUR_TENANT_ID,
'endpoint' => IDENTITY_SERVICES_URL,
// Instead of account/key you can use this:
// 'username' => YOUR_USERNAME,
// 'password' => YOUR_PASSWORD,
);
Bootstrap::setConfiguration($settings);
~~~
Basically, what we do above is declare an associative array of
configuration parameters and then tell HPCloud::Bootstrap to set these
as the default configuration.
Once the above is done, all of those PHP stream and file functions will
just work. All you need to do is pass them `swift://` URLs, and they
will do the rest.
## The Format of Swift URLs
Early in the tutorial we saw some swift URLs like this:
`swift://Example/my_file.txt` . What is this URL referencing?
The URL above has three important parts, in the form
`swift://CONTAINER/OBJECT_NAME`.
- *swift://*: This is the schema. This part of the URL tells PHP to pass
the request to the HPCloud stream wrapper. (Siwft, by the way, is the
[OpenStack name for object storage](http://openstack.org/projects/storage/).
- *Example*: This is the *container name*. In Object Storage parlance, a
container is a place to store documents. One account can have lots of
containers, and each container can have lots of objects.
- *my_file.txt*: This is the object name. An object is basically the
same as a file.
Swift does not support directories, but it does allow slashes in object
names. So `swift://Example/this/is/my/file.png' checks the container
*Example* for the object named `this/is/my/file.png`.
(For power users, there are some fancy operations you can do to treat
Swift filename parts as if they were directories. Check out
HPCloud::Storage::ObjectStorage::Container.)
## Using Stream Contexts for Authentication
Sometimes it is better to pass authentication information directly to
the stream or file function, instead of relying upon a global
configuration. PHP provides for this with **stream contexts**.
Stream contexts have one major downside: Not all PHP functions accept
stream contexts. Here are some notable examples:
- file_exists()
- is_readable()
- stat()
(Basically, anything that calls the underlying `stat(3)`.)
The advantage, though, is that each call can have its own authentication
data. This is good for supporting multiple accounts, and can also be
used to optimize long-term performance (e.g. by saving authentication
tokens in a database and re-using them).
Here's how a stream context is used:
~~~{.php}
<?php
require_once __DIR__ . '/../src/HPCloud/Bootstrap.php';
use \HPCloud\Bootstrap;
Bootstrap::useAutoloader();
Bootstrap::useStreamWrappers();
$cxt = stream_context_create(array(
'swift' => array(
'account' => YOUR_ACCOUNT_NUMBER,
'key' => YOUR_SECRET_KEY,
'tenantid' => YOUR_TENANT_ID,
'endpoint' => IDENTITY_SERVICES_URL,
// Instead of account/key you can use this:
// 'username' => YOUR_USERNAME,
// 'password' => YOUR_PASSWORD,
),
));
print file_get_contents('swift://Example/my_file.txt', FALSE, $cxt);
?>
~~~
The main difference is the creation of `$cxt` using PHP's
`stream_context_create()`. To fully understand this, you may want to
take a look at the [PHP documentation](http://us3.php.net/manual/en/book.stream.php)
for streams.
## Summary
This tutorial is focused on using stream wrappers to interact with your
HPCloud Object Storage service. We focused on configuring the
environment for transparently using PHP functions like `fopen()` and
`file_get_contents()` to work with objects in HPCloud's object storage.
This is just one way of interoperating with the HPCloud library. For
more detail-oriented work, you may find the Object Oriented facilities
better suited. You can read [the OO tutorial](@ref oo-tutorial) to learn
more about that.
Addidtionally, you may wish to learn more about the internals of the
stream wrapper, the main class,
HPCloud::Storage::ObjectStorage::StreamWrapper, is well-documented.