Using the Rackspace PHP SDK

As a recap from my previous article, CloudFiles is a an online storage service for your static content.

Rackspace provides a Software Development Kit (SDK) for multiple programming languages. They store their PHP SDK on GitHub. The PHP SDK requires PHP 5 with the following modules: cURL, FileInfo and mbstring.

In this tutorial we are going to review use of the PHP SDK with CloudFiles. Not all parts of the API will be covered but you will get a great start.

Once you download the SDK you only need the following files and folders:

  • share/
  • cloudfiles.php
  • cloudfiles_exceptions.php
  • cloudfiles_http.php

Your first flight

Starting off we have some basic tasks. We need to load the cloudfiles.php file, authenticate with CloudFiles, and create a connection using our authentication token.

<?php
$your_username = 'jeffk';
$your_api_key = 'longrandomapikey';

require 'cloudfiles.php';

/**
 * Authenticate using your Rackspace Cloud username and your API key obtained from the control panel
 **/
$auth = new CF_Authentication($your_username, $your_api_key);

/**
 * If you use Cloud Files in the U.K. use
 **/
$auth = new CF_Authentication($your_username, $your_api_key, null, UK_AUTHURL);

$auth->authenticate();


/**
 * Now we create the connection with our CF_Authentication instance
 **/
$connection = new CF_Connection($auth);
?>

It’s that simple. Now that we’re connected our next step is to interact with a container.

Containers

We can create, delete, list, and open different containers. To interact with any container we are going to use our $connection object we created above.

Lets go through creating a container that stores our files.

<?php
/**
 * To create a container, use the $connection variable and call the create_container method. If the container
 * already exists it will return a container instance and NOT overwrite the container.
 **/
$images = $connection->create_container("images");
?>

This will return a container object. In the example we named it $images. This will be used to manipulate the container along with any objects in it. If you need to interact with any objects in a container you have to use the create_container method to to access it. Since the container already exists, it will return the instance and it won’t overwrite it.

Now, deleting a container that is no longer needed. Note: you cannot remove a container that has objects (files) in it. If there are files inside it you must remove them all prior to deleting the container. At the end of the article there is a snippet for removing all objects and then deleting the container.

<?php
/**
 * To delete a container call the delete_container method.
 **/
$connection->delete_container("images");
?>

With these actions done, how about getting the containers? If you want an array of your containers with various information you can use the get_containers method.

<?php
/**
 * Get an array of your available containers and display them.
 **/
$containers = $connection->get_containers();

foreach($containers as $container) {
    echo 'Name: '. $container->name;
    echo 'Number of Objects: '. $container->count;
    echo 'Bytes Stores: '.$container->bytes;
}
?>

If you only want the names of the containers we have the list_containers method:

<?php
$containers = $connection->list_containers();
print_r($containers); // Returns Array([0] => "images")
?>

Making it available to the CDN

By default all containers are private. To make them available on the Content Delivery Network and accessible by a url, we have to tell the API to make the container public. Naturally we can return it to private if need be.

<?php
/**
 * To make a container public use the containers instance and call make_public. You can      * optionally include a timestamp for how long the file is cached on the CDN network. The    * default is 86400 (1 day)
 * Calling this method returns the URI the container is available at.
 **/
$public_uri = $images->make_public();

/**
 * You can also get the URI by calling the cdn_uri or cdn_ssl_uri attributes
 **/
$uri => $images->cdn_uri;
$https_uri = $images->cdn_ssl_uri;

/**
 * To set a public container private you can call make_private. However, all the files in this container will still be available until the cache time expires.
 **/
$images->make_private();
?>

Objects, objects, objects

To create an object we have to carry over our container instance and use the create_object method with the name of the file. Once we do that, we have to send the contents of the file. There are two ways to do that. The easiest way is to use the load_from_filename method so it will gather all the information for us. The second way we specify the file and the size.

<?php
$avatar = $images->create_object('jeffs_avatar.jpg');
$avatar->load_from_filename('/home/user/photos/jeffs_avatar.jpg');

$file_name = '/home/user/photos/jeffs_avatar.jpg');
$file_size = (float) sprintf("%u", filesize($file_name));
$fp = open($file_name, 'r');
$avatar->write($fp, $file_size);

?>

To get a private object we can use the steam method. This works really well for protecting content. It’s not just limited to images either, if you wanted to restrict access to a pdf document for your members only, this would be ideal.


<?php
$img = $images->get_object('jeff.jpg');

header('Content-Type: '.$img->content_type);
$output = fopen("php://output", "w");
$img->stream($output);
fclose($output);
?>

To delete an object we need to use our container and call the delete_object method.

<?php
$images->delete_object('jeff.jpg');
?>

Finishing Up. A few working examples

Here we have an example of scanning a folder for .jpg files and uploading them to Rackspace Cloud Files.

<?php

$api_username = 'jeffk';
$api_key = 'myapikey';

$file_path = '/home/user/images';

require 'cloudfiles.php';

$auth = new CF_Authentication($api_username, $api_key);
$auth->authenticate();

$connection = new CF_Connection($auth);
$images = $connection->create_container("images");
$url = $images->make_public();
echo 'The url is '.$url;


/**
 * Now that we have our connection and access to the container lets get our files.
 **/
if ($h = opendir($file_path)) {
    /**
     * We just opened the directory and now we are going to scan that directory for any files
     **/
    while (false !== ($file = readdir($h))) {

        /**
         * Now we are going to get the extension of the file. If it matches "jpg" then we are going to upload it.
         * Otherwise we are going to ignore it.
         **/
        $get_extension = explode('.', $file);
        if ($get_extension[count($get_extension)-1]=='jpg') {

            /**
             * Lets create the object and send it to CloudFiles
             **/
            $img = $images->create_object($file);
            $img->load_from_filename($file_path.'/'.$file);

            /** Now we delete the image so we don't try to upload it again if we rerun the script **/
            unset($img);
        }
    }
    /**
     * Close the handler for good measure
     **/
    closedir($h);
}
?>

The next example is deleting a container that already contains objects.

<?php
$objects = $images->list_objects();
if (count($objects)>0) {
    foreach($objects as $o) {
        $images->delete_object($o);
    }
}
$connection->delete_container("images");

?>

What I provided here were a few basic examples. A few things you might add in are returning the url to the objects, error handling, or even making sure there are 1 or more objects waiting to be uploaded before connecting.

Additional Need to Know

If you get an error as seen below you need to update your ca certificates, refer to your OS manual or web host to get them upgraded. After I successfully tested in my development environment I ran into this issue in production.

* About to connect() to lon.auth.api.rackspacecloud.com port 443
* Trying 212.64.148.13... * connected
* Connected to lon.auth.api.rackspacecloud.com (212.64.148.13) port 443
* successfully set certificate verify locations:
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
* Closing connection #0
PHP Fatal error: Uncaught exception 'InvalidResponseException' with message     'Unexpected response (): ' in /usr/share/php/cloudfiles/cloudfiles.php:212
Stack trace:
#0 /var/www/html/cloudtest.php(18): CF_Authentication->authenticate()
#1 {main}
thrown in /usr/share/php/cloudfiles/cloudfiles.php on line 212

Fatal error: Uncaught exception 'InvalidResponseException' with message 'Unexpected     response (): ' in /usr/share/php/cloudfiles/cloudfiles.php:21

Next, Rackspace uses exceptions when errors occur. Wrapping your code in try{ } catch() { } blocks will allow you to get the error message instead of an “ Uncaught exception….” Listed below you can see the different exception classes they use and that they only extend the Exception class provided by php.

class SyntaxException extends Exception { }
class AuthenticationException extends Exception { }
class InvalidResponseException extends Exception { }
class NonEmptyContainerException extends Exception { }
class NoSuchObjectException extends Exception { }
class NoSuchContainerException extends Exception { }
class NoSuchAccountException extends Exception { }
class MisMatchedChecksumException extends Exception { }
class IOException extends Exception { }
class CDNNotEnabledException extends Exception { }
class BadContentTypeException extends Exception { }
class InvalidUTF8Exception extends Exception { }
class ConnectionNotOpenException extends Exception { }

If you were to attempt to remove a container that still had objects in it, the software development kit would throw a NonEmptyContainerException exception that you have to watch for.

<?php
/**
* Try to run the code
**/

try {
    $connection->delete_container("images");
}
/**
* If there was an exception thrown, catch it and display the message
**/

catch(NonEmptyContainerException $e) {
    echo $e->getMessage();
}

If our container wasn’t empty it would display “Container must be empty prior to removing it”. If you didn’t catch the error it would provide an output such as:

Fatal error: Uncaught exception 'NonEmptyContainerException' with message 'Container    must be empty prior to removing it.' in /Users/kreitje/Development/test/    cloudfiles.php:560 Stack trace: #0 /Users/kreitje/Development/test/index.php(25):   CF_Connection->delete_container('images') #1 {main} thrown in /Users/kreitje/   Development/test/cloudfiles.php on line 560

If developing an application that customers will interact with you will want to catch any exception. Sometimes the error that gets displayed shows sensitive information. Above, you can see where my files are stored. Depending on the error, it’s possible that your API credentials may be displayed on the browser page.

In the software development kit there’s a docs folder that goes over these methods, along with a few extra ones. Now that you have the basics down and know where the documentation is, I challenge you to create a project that interacts with Rackspace CloudFiles.

Artush Images on Shutterstock

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • kay

    this is a very good tutorial

  • isaycopys

    Good post, I want to get information.

  • Aenknice

    Very well composed articles, Enjoyed that.

  • pletcherevz

    Here let me learn more knowledge!

  • Empogssom

    I cannt upload image file in new topic. Use only jpeg files.

    Can you tell me step by step how to make it?

  • Soymnsymn

    I will stay for a long time on this forum. Thank you!

  • ESCOWEVOZYVIC

    I became very happy to seek out this web-site.I wanted to I appreciate your time and effort for this wonderful read!! I undoubtedly enjoying each small little it and I’ve you bookmarked to take a look at new stuff you blog post.

    Can I just say what a relief to locate someone who really knows what theyre speaking about on the web.

  • elerianer

    I haven’t checked in here for a while since I thought it was getting boring, but the last several posts are great quality so I guess I will add you back to my daily bloglist. You deserve it my friend

  • Galuszkalbd

    you use a excellent blog here! do you want to have the invite posts in this little weblog?

  • http://techtrace.wordpress.com Vishal Biyani

    Thanks for your comment. Hope you find other reads too useful!