cedricziel/flysystem-gcs

Flysystem adapter for Google Cloud Storage (GCS) that uses gcloud-php

v2.0.2 2018-03-12 18:54 UTC

README

Build Status Scrutinizer Code Quality Code Coverage

Flysystem Adapter for Google cloud storage using the gcloud PHP library

Installation

Using composer:

composer require cedricziel/flysystem-gcs

How-To

use CedricZiel\FlysystemGcs\GoogleCloudStorageAdapter;
use League\Flysystem\Filesystem;

$adapterOptions = [
    'projectId' => 'my-project-id',
    'bucket'    => 'my-project-bucket.appspot.com',
    'prefix'    => 'my-path-prefix/inside/the/bucket',
];
$adapter = new GoogleCloudStorageAdapter(null, $adapterOptions);

$filesystem = new Filesystem($adapter);

Authentication

This library utilizes the PHP library google/cloud, which in turn uses google/auth.

Why is this important? It's important, because if you're authenticated locally, through the gcloud command-line utility, or running on a Google Cloud Platform VM, in many cases you are already authenticated, and you don't need to do anything at all, in regards to authentication.

For any other case, you will most probably want to export the environment variable GOOGLE_APPLICATION_CREDENTIALS with a value of the absolute path to your service account credentials that is authorized to use the Storage: Full Access oAuth2 scope, and you're all set.

All examples, including tests, make use of this behaviour.

If that's not what you want, you can create your own StorageClient object that's authenticated differently and pass it to the adapter class constructor as first argument.

Demo

There's a demo project that shows simple operations in a file system manager.

Public URLs to StorageObjects

The Adapter ships with 2 different methods to generate public URLs:

  • a flysystem plugin that exposes a getUrl($path) method on your FilesystemInterface instance
  • a getUrl($path) method on the adapter itself to generate the URL

Read below to know when you will want to use the one or the other.

Flysystem Plugin

The standard way to generate public urls with this adapter would be to add a flysystem plugin to your FilesystemInterface instance.

The plugins needs a piece of configuration, telling it whether and which bucket to use in combination with the standard accessible https://storage.googleapis.com/bucket/object.url, or with a custom CNAME URL such as http://storage.my-domain.com.

Notice that GCS public access via CNAMEs is http only (no https).

Example: Standard public URL to bucket

Supposed you have a bucket my-application-bucket, configure the plugin as follows:

// create your adapter as usual
$adapter = new GoogleCloudStorageAdapter(..);
// add it to your `FilesystemInterface` instance
$filesystem = new Filesystem($adapter);

// create your configuration
$path = 'text-object.txt';
$config = ['bucket' => 'my-application-bucket'];
$filesystem->addPlugin(new GoogleCloudStoragePublicUrlPlugin($config));
$publicUrl = $filesystem->getUrl($path);

// $publicUrl == 'https://storage.googleapis.com/my-application-bucket/text-object.txt';

Example: Standard public URL to bucket with directory prefix

Supposed you have a bucket my-application-bucket with a directory prefix of my/prefix, append the prefix separated by a slash to the bucket name:

// create your adapter as usual
$adapter = new GoogleCloudStorageAdapter(null, ['prefix' => 'my/prefix', ...]);
// add it to your `FilesystemInterface` instance
$filesystem = new Filesystem($adapter);

// create your configuration
$path = 'text-object.txt';
$config = ['bucket' => 'my-application-bucket/my/prefix'];
$filesystem->addPlugin(new GoogleCloudStoragePublicUrlPlugin($config));
$publicUrl = $filesystem->getUrl($path);

// $publicUrl == 'https://storage.googleapis.com/my-application-bucket/my/prefix/text-object.txt';

Example: Custom domain to bucket

Supposed you have setup a CNAME assets.example.com pointing to the public endpoint mentioned in the documentation, you would configure the plugin as follows:

// create your adapter as usual
$adapter = new GoogleCloudStorageAdapter(..);
// add it to your `FilesystemInterface` instance
$filesystem = new Filesystem($adapter);

// create your configuration
$path = 'text-object.txt';
$config = ['url' => 'http://assets.example.com'];
$filesystem->addPlugin(new GoogleCloudStoragePublicUrlPlugin($config));
$publicUrl = $filesystem->getUrl($path);

// $publicUrl == 'http://assets.example.com/text-object.txt'

Example: Custom domain to bucket with directory prefix

Supposed you have setup a CNAME assets.example.com pointing to the public endpoint mentioned in the documentation, and your filesystem uses a directory prefix of my/prefix you need to append the prefix to the url in the configuration and would configure the plugin as follows:

// create your adapter as usual
$adapter = new GoogleCloudStorageAdapter(null, ['prefix' => 'my/prefix', ...]);
// add it to your `FilesystemInterface` instance
$filesystem = new Filesystem($adapter);

// create your configuration
$path = 'text-object.txt';
$config = ['url' => 'http://assets.example.com/my/prefix'];
$filesystem->addPlugin(new GoogleCloudStoragePublicUrlPlugin($config));
$publicUrl = $filesystem->getUrl($path);

// $publicUrl == 'http://assets.example.com/my/prefix/text-object.txt'

getUrl on the adapter / Laravel 5

The Storage services used in Laravel 5 do not use flysystem plugins.

The Laravel 5 specific flysystem instance checks if there's a getUrl method on the adapter object.

This method is implemented on the Adapter, which is why you can add the adapter directly and use it right away:

// create the adapter
Storage::extend('gcs', function($app, $config) {
    $adapter = new GoogleCloudStorageAdapter(null, ['bucket' => 'my-bucket', ...]);
    // add it to your `FilesystemInterface` instance
    return new Filesystem($adapter);
});

// register a new disk of type 'gcs' and name it 'gcs'

// use it
$gcs = Storage::disk('gcs');
$path = 'test-laravel.txt';
$gcs->put($path, 'test-content', AdapterInterface::VISIBILITY_PUBLIC);

$publicUrl = $gcs->url($path);
// $publicUrl == 'https://storage.googleapis.com/my-application-bucket/test-laravel.txt';

Development

Some tests require actual access to GCS. They can be configured through the environment.

variable meaning
GOOGLE_APPLICATION_CREDENTIALS absolute path to the service account credentials *.json file
GCLOUD_BUCKET name of the bucket to perform the tests on
GCLOUD_PROJECT the cloud project to use

License

MIT