Installation
composer require arthem/google-api-bundle
Ensure arthem/google-api is also installed (dependency).
Enable the Bundle
Add to config/bundles.php (Symfony 4+):
return [
// ...
Arthem\Bundle\GoogleApiBundle\ArthemGoogleApiBundle::class => ['all' => true],
];
Configure Credentials
Create a google_api.yaml in config/packages/:
arthem_google_api:
client_id: 'YOUR_CLIENT_ID.apps.googleusercontent.com'
client_secret: 'YOUR_CLIENT_SECRET'
project_id: 'your-project-id'
auth_uri: 'https://accounts.google.com/o/oauth2/auth'
token_uri: 'https://oauth2.googleapis.com/token'
redirect_uri: 'https://your-app.com/google/callback'
scopes: ['https://www.googleapis.com/auth/drive']
First Use Case: OAuth Flow
Use the GoogleAuthService to initiate authentication:
use Arthem\Bundle\GoogleApiBundle\Service\GoogleAuthService;
class AuthController extends AbstractController
{
public function __construct(private GoogleAuthService $googleAuth)
{
}
public function login()
{
return $this->googleAuth->getAuthorizationUrl();
}
public function callback(Request $request)
{
$token = $this->googleAuth->handleCallback($request);
// Store token and proceed...
}
}
getAuthorizationUrl().handleCallback().access_token and refresh_token in your DB/user session.refreshToken() when the access token expires.// Example: Refreshing a token
$token = $this->googleAuth->refreshToken($storedRefreshToken);
Use the GoogleApiClient service to interact with Google APIs (e.g., Drive, Calendar):
use Arthem\Bundle\GoogleApiBundle\Service\GoogleApiClient;
class DriveService
{
public function __construct(private GoogleApiClient $client)
{
}
public function listFiles()
{
$service = $this->client->getService('drive', 'v3');
$results = $service->files->listFiles()->execute();
return $results->getFiles();
}
}
Inject services directly into controllers/services:
public function __construct(
private GoogleAuthService $auth,
private GoogleApiClient $client
) {}
Extend functionality by listening to bundle events (e.g., google.api.token.refresh):
# config/services.yaml
services:
App\EventListener\GoogleTokenListener:
tags:
- { name: kernel.event_listener, event: google.api.token.refresh, method: onTokenRefresh }
Since this is a Symfony bundle, bridge it with Laravel via:
Service Providers: Create a Laravel service provider to register the bundle’s services.
namespace App\Providers;
use Arthem\Bundle\GoogleApiBundle\ArthemGoogleApiBundle;
use Illuminate\Support\ServiceProvider;
class GoogleApiServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->register(ArthemGoogleApiBundle::class);
$this->app->bind(
'google.auth',
\Arthem\Bundle\GoogleApiBundle\Service\GoogleAuthService::class
);
}
}
Configuration: Load the YAML config in config/google.php and bind it to the bundle’s expected structure.
Cache tokens in Laravel’s cache or session to avoid repeated refreshes:
$token = cache()->remember('google_token_' . $userId, now()->addHours(1), function () use ($user) {
return $this->googleAuth->refreshToken($user->refresh_token);
});
Missing google-api Dependency
The bundle requires arthem/google-api (not auto-installed). Manually require it:
composer require arthem/google-api
Scopes Configuration
scopes in google_api.yaml match the API’s requirements (e.g., https://www.googleapis.com/auth/drive for Drive API).403 Forbidden errors.Redirect URI Mismatch
The redirect_uri in config must match the URI registered in Google Cloud Console. Mismatches will fail the OAuth flow.
Token Expiry Handling Access tokens expire (~1 hour). Always:
refresh_token for future use.Symfony-Specific Assumptions
HttpFoundation and DependencyInjection. In Laravel, wrap services or mock dependencies where needed.Enable Debug Logging
Add to google_api.yaml:
debug: true
Logs will appear in Symfony’s monolog or Laravel’s log channel.
Common Errors
invalid_grant: Refresh token expired or revoked. Request a new one via OAuth.redirect_uri_mismatch: Double-check redirect_uri in both config and Google Cloud Console.invalid_client: Verify client_id and client_secret are correct.Custom Services
Extend GoogleApiClient to add API-specific methods:
class CustomGoogleClient extends GoogleApiClient
{
public function getUserPhotos($userId)
{
$service = $this->getService('people', 'v1');
return $service->people->get(...);
}
}
Event Dispatching Trigger custom events for token refreshes or API calls:
$this->dispatchBrowserEvent('google:token_refreshed');
Configuration Overrides Override bundle config via environment variables:
# .env
GOOGLE_API_CLIENT_ID=your_client_id
GOOGLE_API_CLIENT_SECRET=your_secret
Then bind these in your service provider.
Batch API Calls
Use batch() in the Google API client to reduce HTTP requests:
$batch = $this->client->getService('drive', 'v3')->createBatch();
$batch->add($service->files->get(...));
$batch->add($service->files->listFiles(...));
$results = $batch->execute();
Lazy-Load Services Initialize Google API services only when needed to avoid connection overhead:
private function getDriveService()
{
return $this->client->getService('drive', 'v3');
}
How can I help you explore Laravel packages today?