google/cloud-storage
Idiomatic PHP client for Google Cloud Storage. Upload, download, and manage buckets/objects, set ACLs, and use the gs:// stream wrapper. Part of the Google Cloud PHP suite with full API docs and authentication guidance.
composer require google/cloud-storage
.env or service account):
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
use Google\Cloud\Storage\StorageClient;
$storage = new StorageClient();
$bucket = $storage->bucket('your-bucket-name');
// Upload a file
$bucket->upload(fopen('local-file.txt', 'r'), [
'name' => 'remote-file.txt',
'predefinedAcl' => 'publicRead'
]);
$storage->registerStreamWrapper()) for file_get_contents('gs://...') support.// Upload with metadata
$bucket->upload(
fopen('file.pdf', 'r'),
[
'name' => 'uploads/file.pdf',
'metadata' => ['author' => 'John Doe'],
'cacheControl' => 'public, max-age=3600'
]
);
// Download to local path
$object = $bucket->object('file.pdf');
$object->downloadToFile('local-copy.pdf');
// Stream to response (Laravel)
return response()->stream(
$object->createReadStream(),
200,
['Content-Type' => 'application/pdf']
);
// Create bucket with custom options
$bucket = $storage->createBucket('new-bucket', [
'storageClass' => 'STANDARD',
'location' => 'US',
'versioning' => ['enabled' => true]
]);
// List objects with pagination
$objects = $bucket->objects(['prefix' => 'logs/']);
foreach ($objects as $object) {
// Process each object
}
$object = $bucket->object('private-file.pdf');
$url = $object->signedUrl(
new \DateTime('+1 hour'),
['response-content-disposition' => 'attachment']
);
$bucket->update([
'lifecycleRules' => [
[
'action' => ['type' => 'Delete'],
'condition' => ['age' => 365]
],
[
'action' => ['type' => 'SetStorageClass', 'storageClass' => 'COLDLINE'],
'condition' => ['age' => 90]
]
]
]);
Service Provider Binding:
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->singleton(StorageClient::class, function () {
return new StorageClient([
'keyFilePath' => env('GOOGLE_CREDENTIALS_PATH'),
'projectId' => env('GOOGLE_CLOUD_PROJECT')
]);
});
}
Facade for Convenience:
// app/Facades/CloudStorage.php
public static function upload(string $path, string $destination, array $options = [])
{
return app(StorageClient::class)
->bucket(config('cloud-storage.bucket'))
->upload(fopen($path, 'r'), $options);
}
Event Dispatching:
// After upload
event(new FileUploaded($object->name(), $object->metadata()));
Queue Jobs for Large Files:
// app/Jobs/ProcessVideoUpload.php
public function handle()
{
$bucket->object($this->path)->downloadToFile(storage_path('temp.mp4'));
// Process with FFmpeg, etc.
}
Authentication:
roles/storage.admin or equivalent.keyFile: Use keyFilePath in v1.48.4+.GOOGLE_APPLICATION_CREDENTIALS over hardcoding.Stream Handling:
fopen with w+ mode for writes.resumableUpload for files >5MB to avoid timeouts.
$bucket->upload(
fopen('large-file.iso', 'r'),
['resumable' => true]
);
Path Traversal:
name parameter in upload() to prevent ../ attacks.hierarchicalNamespace: true for folder-like paths.Soft Delete:
restore() to recover soft-deleted objects.Checksum Validation:
'checksum' => 'MD5' if needed.$object->update(['md5Hash' => md5_file('local-file.txt')]);
Enable Debugging:
$storage = new StorageClient([
'debug' => true,
'logPath' => storage_path('logs/google-storage.log')
]);
storage_path('logs/google-storage.log').Common Errors:
InvalidArgumentException: Check bucket/object names for invalid characters.Google\Cloud\Core\Exception\GoogleException: Inspect getMessage() for API-specific errors (e.g., quota limits).Retry Logic:
$storage = new StorageClient([
'retry' => [
'maxAttempts' => 3,
'timeout' => 30
]
]);
Custom Metadata:
Google\Cloud\Storage\StorageObject to add Laravel-specific metadata:
$object->metadata['laravel_model_id'] = $user->id;
$bucket->updateObject($object);
Event Listeners:
// app/Providers/EventServiceProvider.php
protected $listen = [
'Google\Cloud\Storage\Events\ObjectFinalized' => [
'App\Listeners\ProcessUploadedFile'
]
];
Middleware for Signed URLs:
public function handle($request, Closure $next)
{
if ($request->is('storage/*')) {
$this->validateSignedUrl($request->path());
}
return $next($request);
}
Flysystem Adapter:
league/flysystem-google-cloud-storage for unified file system operations:
$adapter = new GoogleCloudStorageAdapter($storage, 'bucket-name');
$filesystem = new League\Flysystem\Filesystem($adapter);
Parallel Uploads:
parallelUpload for multiple files:
$bucket->parallelUpload([
'file1.txt' => fopen('local1.txt', 'r'),
'file2.txt' => fopen('local2.txt', 'r')
]);
Cache-Control Headers:
$bucket->upload(..., [
'cacheControl' => 'public, max-age=31536000, immutable'
]);
Compression:
$bucket->upload(..., [
'contentEncoding' => 'gzip'
]);
Batch Operations:
batch() for multiple operations (e.g., copy/move/delete):
$batch = $bucket->batch();
$batch->copy('source.txt', 'destination.txt');
$batch->delete('temp.txt');
$batch->execute();
How can I help you explore Laravel packages today?