Weave 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

Google Drive Bundle Laravel Package

vatri/google-drive-bundle

Symfony bundle that integrates Google Drive into your application, simplifying Google API authentication and configuration so you can manage Drive files and folders through Symfony services.

View on GitHub
Deep Wiki
Context7

Getting Started

vatri/google-drive-bundle wraps google/apiclient in a Symfony bundle and exposes a ready-to-use Google Drive v3 client built from config, so you don't hand-roll the Google\Client bootstrap on every project.

v2.0.0 is a compatibility release, not a feature release. The only change is Symfony 7 support (PR #29). Treat the upgrade as a dependency-constraint exercise first and a code change second.

  1. Check your Laravel version before anything else. Symfony 7 components ship with Laravel 11+ (PHP 8.2+). On Laravel 10 or older you are pinned to vatri/google-drive-bundle:^1.4 — verify with:
    composer why-not vatri/google-drive-bundle 2.0.0
    composer show vatri/google-drive-bundle
    
  2. Install and inspect the actual surface (class/service ids vary by tag — read vendor/vatri/google-drive-bundle/Resources/config/services.* rather than trusting blog posts):
    composer require vatri/google-drive-bundle:^2.0
    
  3. Create credentials in Google Cloud Console: enable the Drive API, then either an OAuth client + refresh token (user data) or a service account (server-to-server, needs a Shared Drive to have quota).
  4. Wire the config into Laravel. There is no package auto-discovery for Symfony bundles, so register the bundle's extension/config manually in a service provider or publish a config/google_drive.php and bind the service yourself.
  5. First use case: list a folder and upload a file to a known folder ID from a queued job — not from a controller.

Implementation Patterns

Bridge the Symfony container into Laravel explicitly. The bundle expects a Symfony extension alias (typically vatri_google_drive) with client_id, client_secret, refresh_token. In Laravel, load that config array from config/services.php, then in a GoogleDriveServiceProvider bind the bundle's Drive service as a singleton:

$this->app->singleton(Drive::class, fn ($app) => /* build from config */ );

Keep credentials in .env and cache the config (php artisan config:cache) so you're not re-parsing YAML-ish arrays per request.

Prefer injecting your own thin wrapper over injecting the vendor service everywhere. A DriveClient class with upload(), listFolder(), export() methods gives you one place to add retries and to swap to masbug/flysystem-google-drive-ext later if you decide you'd rather have Storage::disk('google') semantics than raw API calls.

Do all Drive I/O in queued jobs. Uploads are network-bound and slow; a 20 MB file in a request will hit PHP's max_execution_time before it hits Google's limits.

UploadToDrive::dispatch($localPath, $folderId)
    ->onQueue('drive')
    ->retry(5, fn ($attempt) => $attempt * 30); // 429/5xx friendly

Always send a fields mask. Default Drive responses are huge and will bloat memory on listings:

$files->listFiles([
    'q' => sprintf("'%s' in parents and trashed = false", $folderId),
    'fields' => 'nextPageToken, files(id, name, mimeType, size, modifiedTime)',
    'pageSize' => 200,
]);

Loop on nextPageToken — never assume one page.

Store the Drive file ID in your DB, not the filename. Names collide and get renamed; IDs are stable. Add columns drive_file_id, drive_folder_id, drive_mime_type.

Shared Drives need three extra flags on every call: supportsAllDrives => true, includeItemsFromAllDrives => true, and corpora => 'drive' plus driveId on listings. Forget them and you'll silently see zero files.

Google-native files (Docs/Sheets/Slides) can't be downloaded — use files->export() with a target mime type, and cache the result since export is expensive.

Folder hierarchy is just parent IDs; build a path => folderId resolver with a cache (Cache::remember("drive:folder:$path", ...)) instead of walking parents on each upload.

Push notifications (Drive changes.watch) require a public HTTPS webhook, X-Goog-Channel-ID/X-Goog-Resource-State header validation, and channel renewal before expiration (X-Goog-Channel-Expiration). Schedule renewal in the scheduler; expired channels stop silently.

Gotchas and Tips

  • The upgrade itself is the gotcha. v2.0.0 bumps to Symfony 7; if you're on Laravel 10 or pinned Symfony 6.x components, Composer will hold you at 1.4.2 — including in CI where the lock file differs. Diff composer.lock in the PR, don't just bump the constraint and assume green.
  • No Laravel package discovery. composer require alone registers nothing: no facade, no config publish, no migrations. Expect to write the service provider and the config file yourself, and expect php artisan config:cache to surface any env() calls you left in the wrong place.
  • Symfony 7 removed deprecated APIs. If you subclassed or decorated any bundle class (custom Google\Client, extended service), re-run your test suite — deprecation-triggered fatals show up only on the paths you exercise.
  • No PHP requirement visible in the release notes — check the tag's composer.json for the real php floor (Symfony 7 implies 8.2+). Your Docker base image is part of this migration.
  • invalid_grant on refresh is almost always an OAuth consent screen stuck in "Testing" (tokens expire after 7 days) or a rotated/revoked token. Not a package bug — don't chase it in the vendor code.
  • Service accounts have no quota on personal My Drive. Uploads fail with "storage quota exceeded" even though auth succeeds. Use a Shared Drive or domain-wide delegation.
  • Rate limits are normal, not exceptional. 403 userRateLimitExceeded / 429 need exponential backoff with jitter; Laravel's retry() with $attempt * n seconds is enough. Never retry invalid_grant or 404 — those are permanent.
  • Escape q queries. Single quotes in folder/file names break the query string; strip or escape them before interpolating.
  • Set an explicit HTTP timeout on the underlying Guzzle client and use resumable uploads above ~5 MB. Simple uploads buffer the whole file and blow memory_limit on large media.
  • Debugging: catch Google\Service\Exception and log getMessage() plus $e->getErrors() — the top-level message ("A bucket name is needed…" / "insufficient permissions") is often misleading. The bundle doesn't add logging for you.
  • Extension points are thin. The practical options are (a) decorate your own wrapper service, (b) configure the client after construction if the bundle exposes it, or (c) skip the bundle and use google/apiclient directly — for a Laravel-only codebase that's often less work than maintaining the Symfony bridge.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin