schulzefelix/laravel-bigquery
Laravel integration for Google BigQuery: query BigQuery tables from your app using a fluent, Eloquent-style builder, run raw SQL, and manage authentication and configuration through Laravel's config and service container.
Version 1.7.0 raises the platform floor. The package now requires PHP 8.x and Laravel 9+ (Laravel 8 and below are no longer supported), and it pulls a newer symfony/cache. On a modern app the install is unchanged; on a legacy app it is not.
composer require:
php -v # must be 8.0+ (8.1+ recommended to match the Symfony cache branch)
php artisan --version
If you are on PHP 7.4 or Laravel 8, stay on the 1.6.x line and pin explicitly: composer require vendor/package:^1.6.symfony/cache:
composer require vendor/package:^1.7
composer update symfony/cache --with-dependencies
php artisan vendor:publish --tag=...) and confirm the store/adapter wiring still matches your config/cache.php.php artisan cache:clear / your usual profiling (Telescope, Debugbar, or a simple Cache::getStore() sanity check). This validates the Symfony cache layer end-to-end faster than any unit test.Because the package rides on symfony/cache, the mental model is PSR-6/PSR-16 caching underneath Laravel's cache facade — expect remember/rememberForever, TTLs, and tag-aware pools to be the primary surface area.
Use it as a first-class cache store, not a side-channel. Register the store in config/cache.php and go through Cache::store('your-store') so Laravel's facade, events, and testing helpers all keep working:
$value = Cache::store('package-store')->remember(
"report:{$tenantId}:{$month}",
now()->addHours(6),
fn () => $this->buildExpensiveReport($tenantId, $month)
);
Layered caching with remember() + tags where supported. Use tags for group invalidation (per-tenant, per-model) and plain keys for everything else. Treat tags as a capability to detect, not assume — see Gotchas.
Invalidation via model events is the most common day-to-day pattern: an observer or booted() hook calling Cache::store(...)->forget($key) on saved/deleted. Push key generation into a single helper or CacheKey class so read and write sites cannot drift.
PSR interoperability. If your app already consumes Psr\SimpleCache\CacheInterface (or PSR-6 CacheItemPoolInterface) — common in packages and queue workers shared with non-Laravel code — bind the package's pool in a service provider and inject the interface rather than the concrete class. This is where the symfony/cache upgrade pays off: one adapter, two consumption styles.
Warm and stampede-protect. For expensive entries, combine remember with a short lock (Cache::lock()) around the callback, and add a php artisan warm-up command that primes hot keys post-deploy. This matters more with a persistent shared store than it did with file caching.
Testing. Swap the store to array in phpunit.xml (CACHE_DRIVER=array) and, for tag/lock behaviour, use a real Redis in an integration test — array drivers do not reproduce tag or lock semantics.
Upgrade pattern for 1.7.0: bump the package and its Symfony dependency in the same PR as your PHP/Laravel matrix bump, then run the full suite with config:cache cleared. Do not split "upgrade PHP" and "upgrade cache layer" across two deploys; the failure modes overlap.
symfony/cache bump and dropping PHP 7 / Laravel ≤8 — both change your dependency graph. Treat 1.7.0 as a major-version upgrade in your planning even though the version number says minor. Read the symfony/cache CHANGELOG for the branch you land on; adapters removed between Symfony 5 and 6 (e.g. the Doctrine bridge adapter, deprecated PhpArrayAdapter usage) will break you at runtime, not at install time.php: 7.4 or laravel: 8.*, Composer will resolve an older package version instead of failing loudly — you can ship a "successful" build that never tested 1.7.0. Explicitly constrain the matrix and add a composer why-not vendor/package 1.7 check.{ } ( ) / \ @ :. Keys built from URLs, emails, or Class@method strings will throw. Hash or slugify any user-derived segment — this is the single most common runtime error after a cache-layer upgrade.tags() there throws or silently no-ops depending on the path. Detect capability at boot or standardise on Redis/Memcached if your invalidation strategy depends on tags.int|null|DateInterval; PSR-6 expiresAfter() differs slightly, and 0/negative TTLs are treated inconsistently between drivers. Prefer explicit now()->addMinutes(n) and never pass 0 meaning "forever" — use rememberForever.php artisan config:cache bakes the store configuration; if you changed the driver or adapter class during the upgrade, stale bootstrap caches produce confusing "class not found" or "store not defined" errors. Always php artisan optimize:clear after deploying 1.7.0.unserialize() on old payloads can warn or fail. Flush the affected namespace as part of the upgrade deploy, or version your key prefix (v2:).Store contract rather than concrete adapter classes. That keeps you insulated from the next symfony/cache major and lets you swap in TagAwareAdapter, ChainAdapter, or a namespaced pool without touching call sites.Cache::getStore() in tinker tells you instantly which adapter actually resolved — the fastest way to catch a config that quietly kept the old driver after the upgrade.How can I help you explore Laravel packages today?