Installation
Run composer require double-star-systems/google-api-bundle in your Laravel project (note: this is a Symfony bundle, but can be adapted for Laravel via Laravel Symfony Bridge or manually).
Credentials Setup
credentials.json file from the Google Cloud Console.config/google_api_bundle/credentials.json (or configure a custom path in config/google_api.php).Basic Configuration
Add minimal config in config/google_api.php:
return [
'scopes' => ['https://www.googleapis.com/auth/drive'], // Replace with your required scopes
'credentials_file' => env('GOOGLE_CREDENTIALS_PATH', base_path('config/google_api_bundle/credentials.json')),
'token_file' => storage_path('app/google_tokens.json'), // Persist tokens here
'application_name' => 'Your Laravel App',
];
First Use Case
Inject the Google_Client service into a controller or service:
use Google\Client;
class ExampleController extends Controller
{
public function __construct(private Client $googleClient) {}
public function index()
{
$service = new Google\Service\Drive($this->googleClient);
$files = $service->files->listFiles();
return response()->json($files);
}
}
Service Binding: Register the bundle’s service in Laravel’s container (if not using Symfony Bridge):
$this->app->bind('google.client', function ($app) {
return new Google\Client([
'credentials' => $app['config']['google_api.credentials_file'],
'scopes' => $app['config']['google_api.scopes'],
'auth_key_file' => $app['config']['google_api.credentials_file'],
'access_type' => 'offline',
'approval_prompt' => 'force',
]);
});
Lazy Initialization: Use app('google.client') to defer client initialization until first use (avoids early auth prompts).
Auth Flow
$this->googleClient->setAccessToken($token);
$this->googleClient->setAuthConfig($config);
Service Integration
$serviceName = request('service', 'drive');
$serviceClass = "Google\\Service\\$serviceName";
$service = new $serviceClass($this->googleClient);
Token Persistence
token_file:
$this->googleClient->setAccessToken(file_get_contents(storage_path('google_tokens.json')));
Batch Operations
Google\Batch for parallel API calls:
$batch = new Google\Batch($this->googleClient);
$batch->add($service->files->create(...));
$this->googleClient->setAuthConfig($config);
event(new GoogleAuthSuccess($this->googleClient->getAccessToken()));
return Cache::remember("google_{$endpoint}", now()->addHours(1), function () use ($service) {
return $service->files->listFiles()->getFiles();
});
GoogleApiJob::dispatch($this->googleClient, 'drive', 'files.list')->onQueue('google');
Credentials Path
config/google_api_bundle/) may fail in shared hosting. Use env() or Laravel’s config_path():
'credentials_file' => env('GOOGLE_CREDENTIALS_PATH', config_path('google_api_bundle/credentials.json')),
Token File Permissions
token_file is writable by the web server:
chmod 644 storage/app/google_tokens.json
Scopes Misconfiguration
Google_Auth_Exception. Validate scopes against Google’s API docs.Service Descriptor Caching
google_api.php:
php artisan config:clear
Deprecated Methods
google-api-php-client v1.x. Upgrade to v2.x if using newer APIs (adjust service classes accordingly).Enable Debugging
Add to config/google_api.php:
'debug' => env('APP_DEBUG', false),
This enables verbose logging for OAuth flows.
Token Errors
If tokens expire silently, log the token_file contents:
file_put_contents(storage_path('logs/google_token_debug.log'), file_get_contents($tokenFile), FILE_APPEND);
CORS Issues Ensure your Google Cloud project’s APIs & Services > Credentials allows your Laravel app’s domain.
Custom Auth Providers Extend the client with custom auth logic (e.g., JWT):
$this->googleClient->setAuthConfig([
'client_id' => 'custom',
'client_secret' => 'custom',
'auth_provider_x509_cert_url' => 'https://example.com/jwt.pem',
]);
Middleware for Auth Create middleware to auto-refresh tokens:
public function handle($request, Closure $next)
{
if ($this->googleClient->isAccessTokenExpired()) {
$this->googleClient->fetchAccessTokenWithRefreshToken($this->googleClient->getRefreshToken());
}
return $next($request);
}
Dynamic Scopes Load scopes from a database or user roles:
$scopes = Scope::where('user_id', auth()->id())->pluck('scope')->toArray();
$this->googleClient->setScopes($scopes);
Testing Mock the client in tests:
$mockClient = Mockery::mock(Client::class);
$mockClient->shouldReceive('getAccessToken')->andReturn(['access_token' => 'mock_token']);
$this->app->instance(Client::class, $mockClient);
How can I help you explore Laravel packages today?