bogdanfinn/the-games-db-bundle
composer require bogdanfinn/the-games-db-bundle
config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 3):
return [
// ...
bogdanfinn\TheGamesDbBundle\TheGamesDbBundle::class => ['all' => true],
];
GameClient in a controller/service:
use bogdanfinn\TheGamesDbBundle\Client\GameClient;
class GameController extends AbstractController
{
public function __construct(private GameClient $gameClient) {}
public function search(string $query)
{
$results = $this->gameClient->searchGame($query);
return $this->json($results);
}
}
Searching Games
// Basic search (returns array of game IDs + metadata)
$results = $gameClient->searchGame('Call of Duty');
// Paginated search (if API supports it)
$results = $gameClient->searchGame('Zelda', ['page' => 2]);
Fetching Game Details
// By ID (returns full game object)
$game = $gameClient->getGameById(30741); // Example: The Witcher 3
// By slug (if supported)
$game = $gameClient->getGameBySlug('the-witcher-3');
Bulk Operations
// Fetch multiple games (if API supports batch requests)
$gameIds = [30741, 30742, 30743];
$games = $gameClient->getGamesByIds($gameIds);
Caching Responses
Decorate GameClient to cache API responses (e.g., using Symfony Cache component):
$cache = $this->container->get('cache.app');
$key = 'tgdb_game_' . $id;
if ($cache->has($key)) {
return $cache->get($key);
}
$game = $gameClient->getGameById($id);
$cache->set($key, $game, 3600); // Cache for 1 hour
return $game;
Error Handling Wrap API calls in a service to standardize errors:
try {
$game = $gameClient->getGameById($id);
} catch (\Exception $e) {
$this->logger->error('TGDB API Error', ['exception' => $e]);
throw new \RuntimeException('Failed to fetch game data.');
}
Dependency Injection
Prefer constructor injection over service locator ($this->get()):
// Bad: Service locator
$gameClient = $this->get('theGamesDb_game_client');
// Good: Constructor injection
public function __construct(private GameClient $gameClient) {}
API Rate Limiting
use Symfony\Component\HttpClient\RetryableHttpClient;
$client = new RetryableHttpClient($httpClient, [
'max_retries' => 3,
'delay' => 1000, // 1 second
'multiplier' => 2,
'max_delay' => 60000, // 1 minute
]);
Deprecated Methods
Data Format Inconsistencies
searchGame returns IDs, getGameById returns full objects). Normalize data in a DTO or service layer:
class GameDto {
public function __construct(
public int $id,
public string $name,
public ?string $coverUrl = null,
public array $platforms = []
) {}
}
Enable API Debugging Configure the bundle to log raw API responses:
# config/packages/the_games_db.yaml
the_games_db:
debug: true
Check logs for malformed responses or missing data.
Mocking for Tests
Use a mock GameClient in PHPUnit:
$mock = $this->createMock(GameClient::class);
$mock->method('searchGame')
->with('Zelda')
->willReturn([['id' => 123, 'name' => 'Zelda: Breath of the Wild']]);
$this->gameClient = $mock;
Custom API Endpoints Extend the bundle by creating a decorator:
class CustomGameClient extends GameClient
{
public function getGamePlatforms(int $gameId): array
{
$response = $this->httpClient->request('GET', sprintf(
'https://api.thegamesdb.net/Game/%d/platforms',
$gameId
));
return json_decode($response->getContent(), true);
}
}
Register as a service:
services:
App\Service\CustomGameClient:
decorates: theGamesDb_game_client
arguments: ['@App\Service\CustomGameClient.inner']
Configuration Overrides Override default API settings (e.g., base URL, timeout):
# config/packages/the_games_db.yaml
the_games_db:
api_url: 'https://custom-tgdb-api.example.com'
timeout: 30
Event Listeners Listen for API failures to trigger retries or fallbacks:
$eventDispatcher->addListener(
'the_games_db.api.failure',
function (ApiFailureEvent $event) {
if ($event->getStatusCode() === 429) {
// Retry logic
}
}
);
How can I help you explore Laravel packages today?