Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Cloud Storage Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require google/cloud-storage
    
  2. Authentication (via .env or service account):

    GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
    

    Or configure in code:

    $storage = new \Google\Cloud\Storage\StorageClient([
        'keyFilePath' => storage_path('app/google-credentials.json'),
        'projectId' => env('GOOGLE_CLOUD_PROJECT'),
    ]);
    
  3. First Use Case: Upload a file from Laravel’s public disk:

    use Google\Cloud\Storage\StorageClient;
    
    $storage = new StorageClient();
    $bucket = $storage->bucket(env('GOOGLE_CLOUD_BUCKET'));
    
    $bucket->upload(
        fopen(storage_path('app/uploads/example.pdf'), 'r'),
        ['name' => 'processed/example.pdf']
    );
    

Key Entry Points

  • Buckets: $storage->bucket('name')
  • Objects: $bucket->object('path/to/file')
  • Stream Wrapper: $storage->registerStreamWrapper(); (enables gs:// URLs in file_get_contents)

Implementation Patterns

1. Laravel Filesystem Integration

Use the Stream Wrapper to replace local/s3 disks in Laravel’s config/filesystems.php:

'disks' => [
    'gcs' => [
        'driver' => 'google',
        'bucket' => env('GOOGLE_CLOUD_BUCKET'),
        'project_id' => env('GOOGLE_CLOUD_PROJECT'),
        'stream_wrapper' => true, // Enable gs:// URLs
    ],
],

Usage:

Storage::disk('gcs')->put('file.txt', 'Hello, GCS!');
$contents = file_get_contents('gs://my-bucket/file.txt');

2. Resumable Uploads for Large Files

Leverage multipart uploads for files >5MB:

$object = $bucket->upload(
    fopen($localPath, 'r'),
    [
        'name' => 'large-file.zip',
        'resumable' => true,
        'chunkSize' => 5 * 1024 * 1024, // 5MB chunks
    ]
);

3. Signed URLs for Secure Downloads

Generate time-limited URLs for user downloads:

$object = $bucket->object('private-file.pdf');
$url = $object->generateSignedUrl([
    'expiration' => time() + 3600, // 1 hour
    'responseDisposition' => 'attachment; filename="custom-name.pdf"',
]);

4. Lifecycle Management (Soft Delete + Retention)

Configure bucket-level retention policies:

$bucket->update([
    'retentionPeriod' => 365, // Days (immutable)
    'softDelete' => true,
]);

5. Event-Driven Workflows

Use Cloud Storage triggers (via Pub/Sub) to process uploads:

// In a Laravel job queue
$object = $bucket->object('uploaded/image.jpg');
$object->downloadToFile(sys_get_temp_dir() . '/temp.jpg');

// Process with Intervention Image, then save back to GCS

6. Metadata & Custom Properties

Attach metadata to objects (e.g., for Spatie Media Library):

$bucket->upload(
    fopen($localPath, 'r'),
    [
        'name' => 'user-avatar.jpg',
        'metadata' => [
            'user_id' => auth()->id(),
            'mime_type' => 'image/jpeg',
        ],
    ]
);

7. Batch Operations

List and iterate over objects efficiently:

foreach ($bucket->objects() as $object) {
    if ($object->name()->startsWith('logs/')) {
        $object->delete();
    }
}

Gotchas and Tips

Authentication Pitfalls

  1. Service Account Permissions:

    • Ensure the service account has roles/storage.admin (or least-privilege roles like roles/storage.objectAdmin).
    • Debugging: Use GOOGLE_APPLICATION_CREDENTIALS in .env for local testing, but avoid committing credentials.
  2. Deprecated Keys:

    • keyFile and keyFilePath are deprecated. Use environment variables or GOOGLE_APPLICATION_CREDENTIALS instead.

Performance Quirks

  1. Stream Handling:

    • Always close streams after uploads/downloads to avoid memory leaks:
      $stream = fopen($localPath, 'r');
      $bucket->upload($stream, ['name' => 'file.txt']);
      fclose($stream); // Critical!
      
    • For large files, use resumable uploads (see Implementation Patterns).
  2. Stream Wrapper Caveats:

    • gs:// URLs do not support file_put_contents directly. Use $bucket->upload() instead.
    • Permissions: Ensure the service account has storage.objects.get for downloads.
  3. CRC32C Checksums:

    • Enabled by default (v2.0+). Disable with:
      $storage = new StorageClient(['checksum' => 'none']);
      

Debugging Tips

  1. Enable Debug Logging:

    $storage = new StorageClient([
        'debug' => true,
        'logPath' => storage_path('logs/gcs.log'),
    ]);
    
    • Logs HTTP requests/responses for API issues.
  2. Common Errors:

    • InvalidArgumentException: Check bucket/object names (must be lowercase, no / in object names).
    • Google\Cloud\Core\Exception\GoogleException: Inspect the getMessage() for API-specific errors (e.g., quota limits).
  3. Retry Behavior:

    • Configure retries for transient failures:
      $storage = new StorageClient([
          'retry' => [
              'maxAttempts' => 5,
              'timeout' => 30,
          ],
      ]);
      

Extension Points

  1. Custom Metadata Handling:

    • Extend the Google\Cloud\Storage\Object class to add Laravel-specific metadata:
      $object->setLaravelMetadata(['user_id' => auth()->id()]);
      
  2. Event Listeners:

    • Use Laravel’s Storage facade to hook into uploads:
      Storage::disk('gcs')->addListener('afterWrite', function ($event) {
          // Trigger a job to process the uploaded file
      });
      
  3. Hybrid Storage:

    • Combine with Laravel’s FilesystemManager to fallback to local storage:
      $disk = Storage::disk('gcs');
      if (!$disk->exists('file.txt')) {
          Storage::disk('local')->copy('backup/file.txt', 'gcs:file.txt');
      }
      

Security Best Practices

  1. Predefined ACLs:

    • Avoid publicRead in production. Use signed URLs or IAM conditions instead.
    • Example for private uploads with user-specific access:
      $object->update([
          'acl' => [
              [
                  'entity' => 'user-' . auth()->id(),
                  'role' => 'READER',
              ],
          ],
      ]);
      
  2. Object Versioning:

    • Enable bucket versioning to protect against accidental deletes:
      $bucket->update(['versioning' => true]);
      
  3. CORS Configuration:

    • Set CORS rules on the bucket for direct client uploads:
      $bucket->update([
          'cors' => [
              [
                  'origin' => ['https://your-app.com'],
                  'method' => ['GET', 'HEAD', 'PUT'],
                  'responseHeader' => ['Content-Type'],
              ],
          ],
      ]);
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata