Using S3 with CakePHP

Despite the fact I’ve used amazon S3 on and off for the past 3-4 years I’ve never had to integrate the service into anything and on having to do so for a project I’m currently involved in I’ve come across a bit of a misunderstanding of how it works.

I’ve always assumed it was basically access to a file system on a bunch of server space. There was some clever mapping in the background to push the files/directories around but nothing more than that. Turns out my understanding was wrong. I’m sure the files are still pushed around or mapped to huge SANs in a very clever way but amazon S3 does not have the concept of physical directories.

Amazon S3 is simply a map of keys to files at its most basic level. The keys can contain URI mappings but the actual concept of a directory is incorrect. This misunderstanding stems from using third party tools to access S3. It always seemed like you could created a directory in a bucket, but in most of these tools what you are actually doing is creating a specially named file to represent a directory.

This misunderstanding only became apparent when I was using a simple plugin to my system which interfaced with S3. The plugin uploaded physical files, but what I wanted to do was upload directories for the files first. Something which this library didn’t do.

As always there has to be a better way and in fact there most certainly was. I ended up using the excellent PHP S3 class created by Donovan Schönknecht. Using it was a breeze and integrating it with my CakePHP app turned out to be very simple. Below is an example of pushing a file to S3. Its barebones and not a complete example, in the app I’m working on I have the whole thing integrated with RabbitMQ and the Media plugin through a shell but it should give you an idea of how easy this class is to use.

Download the S3 class and place it in your vendors folder, then in your controller assuming the file is already on the server.


public function pushToS3($file) {

  App::import('Vendor', 'S3');
  $s3 = new S3('access_key', 'secret_key');

  $upload_file = $s3->inputFile($file, false);
  $s3->putObject($upload_file, 'bucket', $file, S3::ACL_PUBLIC_READ);

}

Its as simple as that. The third argument to the putObject() function is where you specify the key to the file, if you want a URI with a directory like structure here is where you specify it.

Huge thanks must go to Donovan Schönknecht as his class takes absolutely all of the heavy lifting required out of interfacing with S3. There’s a whole bunch of operations which the class can do, so if you need to do stuff a bit more complex I would highly recommend using this class.

2 thoughts on “Using S3 with CakePHP

  1. Lucas

    Hi man, thanks for an interesting article.
    I’m developing a web application with cakephp and david persson’s media plugin. I’d like to add S3 class to the mix and I was wondering if you succeeded in that…
    David Persson himself recommends this fork (https://github.com/tylerdigital/media), but it’s not documented at all and I’m no pro in the subject. Could you throw a little light here?

    cheers!

    Reply
    1. Al Post author

      I did get it working with the media plugin. It isn’t straightforward the way I have done it as I have offloaded all processing of images and eventual upload to S3 to a cake shell communicated via RabbitMQ. I guess the easiest approach would be to upload things to S3 in the afterSave() method of your model. This should occur after the media plugin has done its stuff.

      The media plugin itself is documented in the docs folder: https://github.com/tylerdigital/media/tree/master/docs

      To be honest it can be a little hard to understand, I’ve been meaning to provide some more documentation to the plugin for a while now detailing my usage of it but am yet to find time.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>