Streams tutorial.
This commit is contained in:
parent
926d2f18d4
commit
89592860a7
41
doc/streams-tutorial-example.php
Normal file
41
doc/streams-tutorial-example.php
Normal 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
238
doc/streams-tutorial.md
Normal 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.
|
Loading…
x
Reference in New Issue
Block a user