softspring/google-cloud-integration-bundle
A Symfony bundle that integrates Google Cloud services into your application, providing ready-made configuration, service clients, and dependency injection wiring so you can connect to Google Cloud APIs with minimal setup.
Decide in the first five minutes whether this package is even applicable. softspring/google-cloud-integration-bundle is a Symfony bundle — a DI extension plus a configuration tree plus YAML service definitions that register google-cloud-php clients into a Symfony container. There is no ServiceProvider, no publishable config stub, no facade, no auto-discovery outside Symfony Flex. If the target app is Laravel, the correct move is to skip the package and use google-cloud-php directly; you can mirror this bundle's config shape (project ID + credentials source + client definitions) in a config/google-cloud.php and a small service provider in about 30 lines. Only reach for the bundle if the app actually boots a Symfony kernel.
Where to look, in order:
README.md — the only place the config root key and the supported GCP surfaces are documented. Do not guess the root key from the package name.src/DependencyInjection/Configuration.php — the authoritative contract: every key, default, and which values are %env()%-backed.src/DependencyInjection/*Extension.php together with src/Resources/config/services*.yaml — the service IDs, aliases, and tags you will autowire or override.composer.json — PHP and Symfony version constraints. This is a 5.x line already past 5.5.10; verify it installs against your framework before you write any code against it.Minimal steps to first working call:
composer require softspring/google-cloud-integration-bundle (pin the constraint explicitly — see Gotchas).config/bundles.php.config/packages/<root_key>.yaml, copying the root key verbatim from Configuration.php.GOOGLE_APPLICATION_CREDENTIALS to a local service-account JSON in dev, and rely on workload identity in GCP. Do not inline a key path in YAML.bin/console cache:warmup — config validation runs at container compile time, so this is where mistakes surface.bin/console debug:config <root_key> and bin/console debug:container --show-private | grep -i google to confirm what actually registered.First use case: pick exactly one GCP surface the bundle exposes (storage, translation, pubsub — whatever the README lists), autowire that client into a single console command, and do one round-trip read against a non-production project. That one command validates credentials, project routing, and endpoint config simultaneously, and it doubles as the smoke test you will want in CI later.
Autowire the bundle's client; never new the SDK class. The whole value proposition is that clients are container-managed, share the resolved config, and are swappable. Constructing Google\Cloud\Storage\StorageClient yourself bypasses all of that and quietly reintroduces credential plumbing into your domain code.
Put a narrow port in front of it. Define your own interface (ObjectStore, TranslationGateway, EventPublisher) bound to an implementation that wraps the bundle's client. Inject the interface everywhere outside the adapter. Google SDK types in your domain layer make framework upgrades expensive and tests awkward — and given this package's release cadence, upgrades are a recurring cost, not a one-off.
Per-environment config with when@ blocks. Keep project ID and credential source env-driven, and override per environment rather than branching inside code:
# config/packages/<root_key>.yaml
<root_key>:
project_id: '%env(GCP_PROJECT_ID)%'
# remaining keys exactly as declared in Configuration.php
when@test:
<root_key>:
project_id: 'test-project'
Testing pattern. The registered clients are ordinary service definitions, so override them in config/services_test.yaml by aliasing the bundle service ID to a fake, or — cleaner — bind your port to an in-memory stub. Never let CI touch real GCP: auth flakiness and quota exhaustion present as test failures and burn hours.
Resolve clients once, reuse them. GCP clients hold HTTP connections and cached auth tokens. Constructor-inject them into services, resolve them once in a command, and pass them down. Do not re-fetch from the container inside a loop.
Centralize credentials across services. The bundle's real payoff shows when several apps or several bundles in one monorepo need GCP. One config file becomes the single source of truth for project and credentials; anything that hardcodes a project string drifts and eventually writes to the wrong environment.
Pin deliberately. If you need behavior from 5.6.0, pin ^5.6. Otherwise pin the exact minor you validated. With this patch turnover, a floating constraint is how a Friday deploy surprises you.
BREAKING, renamed config keys, and removed or renamed service IDs before adopting. Silence is not evidence of safety.5.5.10 with rapid patch releases means active internal churn, and minor bumps are historically where config keys and service definitions move. Your two real API surfaces are Configuration.php and services*.yaml — diff those specifically on every upgrade, not the whole tree.composer.json. For many teams this alone ends the evaluation, and the honest fallback — wiring google-cloud-php yourself — is a couple hours of work.cache:warmup/cache:clear. That's good, but it means a CI pipeline that never warms the container will pass while production fails. Add lint:container and a warmup step to CI.debug command) and verify it in a non-prod smoke run.@internal annotations first — subclassing internals is precisely what minor bumps break.debug:config <root_key> (what the container resolved after when@ merging — the env-specific truth), debug:container --tag=<bundle tag>, debug:container --show-private | grep -i google, and lint:container in CI to catch wiring regressions at build time instead of deploy time.How can I help you explore Laravel packages today?