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 Spreadsheet Bundle Laravel Package

asgoodasnu/google-spreadsheet-bundle

A Symfony bundle for integrating Google Spreadsheets into your application. It provides configuration and container services for authenticating with Google APIs and reading or writing spreadsheet data, simplifying Google Sheets access in Symfony projects.

View on GitHub
Deep Wiki
Context7

Getting Started

Understand what you're actually installing before you composer require anything. This is a Symfony2-era bundle (*Bundle class, DependencyInjection/Extension, config tree registered in app/AppKernel.php). Laravel cannot register or consume it — Laravel reuses Symfony components, not Symfony bundles. In a Laravel app, the only realistic use of this repository is as a pattern reference: it shows how to wire google/apiclient behind a container service with credentials in config. You will re-implement that (~30–50 lines) in a service provider rather than depend on it.

Where to look first, in order:

  1. The bundle's DependencyInjection/Configuration.php and Extension.php — this is where credential keys and service definitions live, and it's the only genuinely reusable idea. Note the parameter names it uses for the client ID, client secret, and refresh token; you'll mirror that shape in config/services.php.
  2. asimlqt/php-google-spreadsheet-client — the actual worker. Be aware it targets the legacy Google Spreadsheets API (GData feeds, ClientLogin/OAuth1), which Google has retired. Do not build new work on it.
  3. google/apiclient against Sheets API v4 — this is where your real code goes.

The first use case to spike (one day, throwaway notebook): authenticate with a service account, read one range from one sheet, append one row. On a Laravel stack that means:

composer require google/apiclient:^2.15
# drop the service-account JSON outside the webroot; reference it via env, never commit it
// config/services.php
'google_sheets' => [
    'credentials' => env('GOOGLE_SHEETS_CREDENTIALS_PATH'),
    'spreadsheet_id' => env('GOOGLE_SHEETS_ID'),
],

Register Google\Client + Google\Service\Sheets as singletons in a SheetsServiceProvider, then $sheets->spreadsheets_values->get($id, 'Sheet1!A1:D10'). Share the target sheet with the service account's client_email — that step, not the code, is where the day gets lost.

Implementation Patterns

Wrap the client behind a domain interface; nothing above it should know Sheets exists. The bundle's whole value proposition is "someone else wired the container for you" — in Laravel you do that wiring yourself once, then hide it.

interface ReportExporter {
    public function append(string $tab, array $row): void;
    public function rows(string $tab): array;
}

Bind SheetReportExporter to ReportExporter in a service provider. Controllers, jobs, and commands depend on the interface. If you later swap Sheets for a real dashboard, the blast radius is one binding.

Read pattern — "spreadsheet as a config table." For pricing tables, feature flags, seed data, content calendars:

  • Read the whole tab with spreadsheets_values->get($id, $tab) in one call — never per-row.
  • Validate the header row on every read ($values[0] equals your expected columns). Human-edited tabs drift; fail loudly rather than mapping positionally into a shifted schema.
  • Cache the parsed result (Cache::remember with a short TTL, e.g. 5 minutes) so a page render doesn't burn a quota unit per request.
  • Map to DTOs immediately; the array-of-arrays should not leak past the adapter.

Write pattern — exports and stakeholder reports. Queue this. A request-cycle write will fail intermittently and take a page down with it.

  • Use spreadsheets_values->append($id, $range, $body, ['valueInputOption' => 'USER_ENTERED']) where humans will read it in the UI (dates/numbers render properly), and 'RAW' where you need the exact string you sent. Pick deliberately; USER_ENTERED silently mangles leading zeros and reformats date strings.
  • Batch appends. A 2,000-row export as 2,000 calls will exhaust quota and hit 429s; chunk into values.append calls of a few hundred rows.
  • Implement exponential backoff with jitter on 429/5xx in a single helper. You will need it on the first nightly run, not the tenth.

Config hygiene that the bundle got right and you should keep:

  • Spreadsheet ID and tab names in config/services.php + .env, never literals in code. Tab names are user-editable and will drift.
  • Credentials path in env; the JSON file outside the webroot; rotate keys on a schedule.
  • One SpreadsheetClient singleton per process — the OAuth handshake is the expensive part.

Local-development pattern worth stealing from the "spreadsheet-as-database" idea: keep a fixture sheet shared only with your dev service account, and have a php artisan sheets:dump command that pulls it into a local JSON fixture. Tests run against the fixture; only a single smoke test touches the live sheet.

Gotchas and Tips

You cannot install this in Laravel and expect it to work. Even composer require asgoodasnu/google-spreadsheet-bundle will either fail on PHP/Symfony constraints or install a package the framework will never boot. Vendor-pulling the underlying asimlqt/php-google-spreadsheet-client gives you the legacy GData surface with none of the bundle's wiring — strictly worse than using google/apiclient directly.

The API is the real trap, not the packaging. asimlqt/php-google-spreadsheet-client speaks the retired Spreadsheets API. This is a rewrite, not a config change; no amount of container wiring saves you. Treat the package as evidence that a spreadsheet→app workflow was wanted, not as a component.

Version pin collisions. The google/apiclient version this bundle implies predates the Google_Client → Google\Client namespace migration. If you try to co-install it alongside a modern google/apiclient, expect a dependency-resolution fight. Don't fork your way out of it — just use the modern client.

Auth failure is the most common and least obvious break. In order of frequency:

  1. The target sheet isn't shared with the service account's client_email. The API returns a 404 that reads like "spreadsheet not found" and sends people hunting for the wrong ID.
  2. An expired or revoked OAuth refresh token (if you went the per-user route).
  3. Credentials file present but with a rotated key not picked up — the client was singleton-cached in a long-running queue worker.

Catch and log these distinctly; a single "Sheets failed" log line will cost someone an afternoon.

Silent schema drift. A human inserts a column; your writer keeps appending and produces misaligned rows with no error. Mitigation: validate the header row before every read and every append batch, and throw a typed exception (SheetSchemaDriftException) that alerts.

Quota limits are the real ceiling. Roughly 300 read requests/minute per project and 60/minute per user, plus a 10M-cell-per-spreadsheet cap. Design for values.batchGet and batched appends from day one; retrofitting batching after the first quota incident is painful.

valueInputOption defaults bite. Omitting it or choosing wrong silently converts "007" → 7, "2024-01-01" → a date serial, and phone numbers into floats. For identifier-like data, RAW and format the destination column as text.

Silent truncation. Values exceeding the 50,000-character cell limit are truncated without error. If you're writing prose or JSON blobs into cells, check length before sending.

Extension point you'd actually want (and must build): a spreadsheet_id + tab indirection so tests can point at a fixture sheet without touching production config. The bundle gives you a config tree; replicate that with a SheetsConfig object resolved from container and overridden in the test binding.

Abandonment math. Zero stars, zero dependents, no issue triage. If you adopt it, you are the maintainer. Set the expectation with your team: the answer to "who fixes this when Google changes the API?" must not be "us, and we've never read the code." For any new Laravel work, the direct google/apiclient path is roughly an engineer-week including backoff, header validation, and tests — and it's a dependency Google maintains rather than one you inherit.

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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log