Objects

Object stores data content, such as documents, images, and so on. You can also store custom metadata with an object.

More information can be found in the official documentation.

In order to work with objects you have to create the service first.

Create

When creating an object, you can upload its content according to a string representation:

$service = $openstack->objectStoreV1();
$container = $service->getContainer('{containerName}');
$object = $container->createObject([
    'name'    => '{objectName}',
    'content' => '{objectContent}',
]);

If that is not optimal or convenient, you can use a stream instead. Any instance of \Psr\Http\Message\StreamInterface is acceptable. For example, to use a normal Guzzle stream:

// You can use any instance of \Psr\Http\Message\StreamInterface
$stream = new \GuzzleHttp\Psr7\Stream(fopen('/path/to/object.txt', 'r'));

$service = $openstack->objectStoreV1();
$container = $service->getContainer('{containerName}');

$object = $container->createObject([
    'name'   => '{objectName}',
    'stream' => $stream,
]);

Create a large object (over 5GB)

For large objects (those over 5GB), you will need to use a concept in Swift called Dynamic Large Objects (DLO). When uploading, this is what happens under the hood:

  1. The large file is separated into smaller segments

  2. Each segment is uploaded

  3. A manifest file is created which, when requested by clients, will concatenate all the segments as a single file

To upload a DLO, you need to call:

$options = [
];

$service = $openstack->objectStoreV1();
$container = $service->getContainer('{containerName}');

$object = $container->createObject([
    'name'             => '{objectName}',
    'stream'           => new \GuzzleHttp\Psr7\Stream(fopen('/path/to/large_object.mov', 'r')),

    // optional: specify the size of each segment in bytes
    'segmentSize'      => 1073741824,

    // optional: specify the container where the segments live. This does not necessarily have to be the
    // same as the container which holds the manifest file
    'segmentContainer' => 'test_segments',
]);

Read

$service = $openstack->objectStoreV1();
$container = $service->getContainer('{containerName}');
$object = $container->getObject('{objectName}');

$object->retrieve();

You can read properties of an object:

printf("%s/%s is %d bytes long and was last modified on %s",
    $object->containerName, $object->name, $object->contentLength, $object->lastModified);

Delete

$service = $openstack->objectStoreV1();
$container = $service->getContainer('{containerName}');
$object = $container->getObject('{objectName}');

$object->delete();

List

$service = $openstack->objectStoreV1();
$container = $service->getContainer('{containerName}');

foreach ($container->listObjects() as $object) {
    /** @var \OpenStack\ObjectStore\v1\Models\StorageObject $object */
}

When listing objects, you must be aware that not all information about a container is returned in a collection. Very often only the MD5 hash, last modified date, bytes used, content type and object name will be returned. If you would like to access all of the remote state of a collection item, you can call retrieve like so:

foreach ($objects as $object) {
    // To retrieve metadata
    $object->retrieve();
}

If you have a large collection of $object, this will slow things down because you’re issuing a HEAD request per object.

By default, PHP generators are used to represent collections of resources in the SDK. The benefit of using generators is that it generally improves performance, since objects are not saved in memory as the iteration cycle goes on; instead, each resource is directly output to the user-defined foreach loop. For all intents and purposes, you interact with generators like any other Traversable object, but to retain collections in memory, you will need to implement your own logic.

Download an object

$service = $openstack->objectStoreV1();
$container = $service->getContainer('{containerName}');
$object = $container->getObject('{objectName}');

$stream = $object->download();

As you will notice, a Stream object is returned by this call. For more information about dealing with streams, please consult Guzzle’s docs.

By default, the whole body of the object is fetched before the function returns, set the 'requestOptions' key of parameter $data to ['stream' => true] to get the stream before the end of download.

Copy object

$service = $openstack->objectStoreV1();
$container = $service->getContainer('{containerName}');
$object = $container->getObject('{objectName}');

$object->copy([
    'destination' => '{newContainerName}/{newObjectName}',
]);

Get metadata

$service = $openstack->objectStoreV1();
$container = $service->getContainer('{containerName}');
$object = $container->getObject('{objectName}');

$metadata = $object->getMetadata();

The returned value will be a standard associative array, or hash, containing arbitrary key/value pairs. These will correspond to the values set either when the object was created, or when a previous mergeMetadata or resetMetadata operation was called.

Replace all metadata with new values

$service = $openstack->objectStoreV1();
$container = $service->getContainer('{containerName}');
$object = $container->getObject('{objectName}');

$object->resetMetadata([
    '{key_1}' => '{val_1}',
    '{key_2}' => '{val_2}',
]);

To see all the required and optional parameters for this operation, along with their types and descriptions, view the reference documentation.

In order to replace all existing metadata with a set of new values, you can use this operation. Any existing metadata items which not specified in the new set will be removed. For example, say an account has the following metadata already set:

Foo: value1
Bar: value2

and you reset the metadata with these values:

Foo: value4
Baz: value3

the metadata of the account will now be:

Foo: value4
Baz: value3

Merge new metadata values with existing

$service = $openstack->objectStoreV1();
$container = $service->getContainer('{containerName}');
$object = $container->getObject('{objectName}');

$object->mergeMetadata([
    '{key_1}' => '{val_1}',
    '{key_2}' => '{val_2}',
]);

To see all the required and optional parameters for this operation, along with their types and descriptions, view the reference documentation.

In order to merge a set of new metadata values with the existing metadata set, you can use this operation. Any existing metadata items which are not specified in the new set will be preserved. For example, say an account has the following metadata already set:

Foo: value1
Bar: value2

and you merge them with these values:

Foo: value4
Baz: value3

the metadata of the account will now be:

Foo: value4
Bar: value2
Baz: value3