gulaandrij/google-sheets-bundle
A Symfony bundle for integrating the Google Sheets API into your application. Configure credentials and use simple services to read, write, and sync spreadsheet data, making Google Sheets a convenient lightweight data source or backend for your project.
The verdict is unchanged: this is a Symfony bundle, not a Laravel package, and the part we would want remains a small abstraction we should own. v1.3.0 does not move the stack-fit blocker an inch — it adds SheetsServiceInterface and a PSR-14 SheetsWriteEvent, both wired through Symfony's container and event dispatcher. But the release materially improves the reference value of the artifact and answers one of our open questions in the process.
What v1.3.0 actually changes for us
CachedSheetsService), a traceable profiler decorator, an in-memory fake, a multi-service registry, discovery/metadata operations, and a write-event contract. That is a real layer, and it expands the list of patterns worth copying even as it reinforces that we should not install it.SheetsServiceInterface captures read/write/discovery/metadata with the escape hatches (client(), driveService()) deliberately excluded from the interface. That is exactly the boundary discipline we specified for App\Contracts\SheetGateway, arrived at independently. Adopt the shape; skip the wiring.operation, spreadsheetId, sheetName, range, rowCount is close to the minimum viable audit record for a write. Reads deliberately dispatch nothing — a defensible call we should mirror, since a per-row read event is an obvious performance trap. Our domain event can copy this field set with minimal thought.InMemorySheetsService::append() now throws MixedRowShapeException on mixed positional/assoc rows and divergent keys, matching production. That tells us two things: the homogeneous-row constraint is a real correctness invariant we must enforce in our adapter, and an in-memory fake implementing the same contract is the right testing posture for our gateway.symfony/framework-bundle, still symfony/dependency-injection version fencing, still a second container paradigm for one service. The ?EventDispatcherInterface addition is last-position and null-safe (nullOnInvalid()), so it is a non-breaking signature change — for Symfony consumers. It is irrelevant to us.Architecture fit
Configuration tree, service definitions, compiler passes, autowire aliases for both SheetsService $<name> and now SheetsServiceInterface $<name>, and a registry. In a Laravel app, symfony/framework-bundle is not present, and importing it to obtain an interface alias and an event dispatcher bridge is a poor trade.revolution/laravel-google-sheets remains the Laravel-native integration and the correct dependency. google/apiclient remains the fallback if the wrapper disappoints.SheetGateway with a decorator seam from day one — a caching decorator and a logging decorator are cheap to add later if the interface exists, expensive to retrofit if it does not.Integration feasibility
symfony/config, symfony/dependency-injection, and symfony/framework-bundle constraints will fence Symfony components that Laravel itself depends on. That is a recurring upgrade tax for a package with no adoption.revolution/laravel-google-sheets (or google/apiclient directly) behind a locally-owned SheetGateway interface and one adapter. Cost estimate holds at one to two engineer-days, with a small increment (roughly a half-day) now allocated to porting the interface shape, the homogeneous-row validation, and an in-memory fake.Technical risk
revolution/laravel-google-sheets and google/apiclient. The former remains the weak link.Retry-After handling, or batch read/write support. The CachedSheetsService exists, but its invalidation semantics are now partly caller-driven via SheetsWriteEvent — which means a cache-staleness class of bug is possible upstream and would be ours to reason about if we copied the pattern.Key questions
Retry-After on quota errors? Still unanswered — highest-priority gap. We must implement this ourselves regardless.CachedSheetsService's TTL and invalidation semantics, and does it depend on the event dispatcher being present? Determines whether the pattern is safe to copy for our own caching layer.Stack fit
google/apiclient behind a thin service provider. The Symfony bundle stays out of the dependency graph by design.App\Contracts\SheetGateway, with GoogleSheetGateway as the sole adapter.SheetGateway with decorator seams from the start (CachingSheetGateway, LoggingSheetGateway), mirroring the bundle's decorator structure but in our idiom. Model the interface on SheetsServiceInterface — read/write/discovery/metadata in the contract, raw client access deliberately excluded.InMemorySheetGateway used in tests, enforcing the same invariants as the real adapter — specifically a MixedRowShapeException-equivalent for mixed positional/assoc rows and divergent keys. The v1.3.0 fix is a direct warning that divergent fake/production behavior silently hides bugs.config/sheets.php, credentials path from env, never committed. Prefer workload identity or a secret manager over a JSON file on disk.Migration path
SheetsServiceInterface, the write-event payload, and InMemorySheetsService's validation. Port the contract shape and the invariant; record the commit SHA or tag v1.3.0 in the design note for provenance.SheetGateway on revolution/laravel-google-sheets. Add retry with jittered backoff on 429/5xx.SheetWritten domain event after successful append/update/clear with the same field set as SheetsWriteEvent. Do not emit on reads. Use it for cache invalidation, audit logging, and sync triggers.Compatibility
composer.lock. With no dependents, upstream regressions go uncaught — pinning is the only safety net.SheetsService since the interface is the advertised contract — one more reason to depend on our own interface, not theirs.Sequencing
Provisioning → spike → source review → adapter with decorator seams → fake and contract tests → read-only consumers → domain events → write consumers → decommission ad-hoc sheet scripts. Freeze the sheet's column layout during rollout or the mapping layer becomes a moving target.
Maintenance
Support
Scaling
Failure modes
Ramp-up
How can I help you explore Laravel packages today?