Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Last Fm Client Bundle Laravel Package

calliostro/last-fm-client-bundle

Symfony bundle that integrates the modern calliostro/lastfm-client with autowiring and Guzzle. Configure your API key, secret, session key, user agent, and optional rate limiter to access Last.fm music data and scrobbling.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Installation:

    composer require calliostro/last-fm-client-bundle
    

    Ensure calliostro/lastfm-client (v2.1.0+ recommended for automatic retry support) is also installed as a dependency.

  2. Configuration: Publish the default config:

    php bin/console config:dump-reference calliostro_lastfm
    

    Update config/packages/calliostro_lastfm.yaml with your API key, rate-limiting settings, and retry behavior:

    calliostro_lastfm:
        api_key: '%env(LASTFM_API_KEY)%'
        rate_limiter: true
        limit: 1000  # requests/hour
        auto_retry: true    # default: true - retries on HTTP 429 / 503
        max_retries: 3      # default: 3
    
  3. First Use Case: Inject Calliostro\LastFm\LastFmClient into a service/controller:

    use Calliostro\LastFm\LastFmClient;
    
    class ArtistController
    {
        public function __construct(private LastFmClient $lastFmClient) {}
    
        public function show(string $artistName)
        {
            $info = $this->lastFmClient->getArtistInfo($artistName);
            return response()->json($info);
        }
    }
    

Implementation Patterns

Autowiring & Dependency Injection

  • Type-hinted injection is fully supported. Prefer constructor injection for services:
    public function __construct(
        private LastFmClient $lastFmClient,
        private RateLimiterInterface $rateLimiter
    ) {}
    
  • Service Locator: Avoid container->get(); use constructor injection or #[Inject] attribute (Symfony 6.4+).

Resilience & Automatic Retries

  • Since v2.1.0 the underlying client retries automatically on Last.fm rate limits (429) and server overload (503), with exponential backoff. Defaults: auto_retry: true, max_retries: 3.
  • Tune per environment:
    # config/packages/test/calliostro_lastfm.yaml
    calliostro_lastfm:
        auto_retry: false
    
    Disable retries in tests or low-latency paths where a fallback path already exists.

Rate Limiting

  • Enable via config (rate_limiter: true). The bundle integrates with symfony/rate-limiter:
    calliostro_lastfm:
        rate_limiter:
            enabled: true
            limit: 1000
            interval: 3600  # seconds
    
  • Rate limiting is client-side throttling; automatic retries are server-side backoff. They complement each other — keep both enabled in production.

Common Workflows

  1. Fetching Data:
    $tracks = $lastFmClient->getRecentTracks('username');
    $albums = $lastFmClient->getTopAlbums('artist', limit: 5);
    
  2. Error Handling: Use try/catch with Calliostro\LastFm\Exception\LastFmException. Retries are exhausted before the exception surfaces, so catch only terminal failures:
    try {
        $lastFmClient->getArtistInfo('nonexistent_artist');
    } catch (LastFmException $e) {
        // Handle API errors after retries have been exhausted
    }
    
  3. Testing: Mock LastFmClient in tests, and disable auto_retry in the test config to avoid slow, flaky suites:
    $this->mock(LastFmClient::class)->shouldReceive('getArtistInfo')->andReturn($mockData);
    

Integration with Symfony Components

  • Messenger: Dispatch API calls as async messages:
    $this->messageBus->dispatch(new FetchArtistInfo($artistName));
    
  • Cache: Cache responses with Symfony Cache component:
    $cache = $this->cacheItemPool->getItem('lastfm_artist_' . $artistName);
    if (!$cache->isHit()) {
        $cache->set($lastFmClient->getArtistInfo($artistName));
        $cache->expiresAfter(3600);
    }
    

Gotchas and Tips

Breaking Changes (v2.0.0)

The v2.1.0 release introduces no breaking changes. If you are still on v1.x, migrate via the v2.0.0 notes below first.

  1. Namespace Update:

    • Old: Calliostro\LastFm\LastFmService
    • New: Calliostro\LastFm\LastFmClient (capital F).
    • Update all service references and imports.
  2. Configuration:

    • Old: lastfm key in config.
    • New: calliostro_lastfm key.
    • Run php bin/console config:dump-reference calliostro_lastfm to regenerate config.
  3. Dependency:

    • Replace calliostro/php-lastfm-api with calliostro/lastfm-client (v2.1.0+ for retry support).
  4. Migration:

Retry Configuration (v2.1.0+)

  • Latency: auto_retry: true means a failing request can take up to max_retries × backoff seconds before throwing. Keep this in mind for synchronous user-facing endpoints — move to Messenger or reduce max_retries there.
  • Compounding: Retries stack on top of client-side rate limiting. A burst of 429s can amplify queue pressure; monitor for thundering-herd symptoms.
  • Idempotency: All Last.fm read endpoints are safe to retry. If you wrap write-style operations in custom clients, verify idempotency before relying on auto_retry.
  • Observability: Log retries by decorating LastFmClient or via the BeforeRequest/AfterResponse events — a 3-retry request is a signal that your rate limiter needs tuning.

Debugging

  • Rate Limiting:
    bin/console debug:container symfony_rate_limiter
    
    Customize limits per endpoint by overriding LastFmClient or using middleware.
  • Retries: Temporarily set max_retries: 1 and auto_retry: false to confirm whether failures are transient (429/503) or genuine (invalid artist, auth).
  • API Errors:
    calliostro_lastfm:
        debug: true
    
    Logs will include raw API responses for troubleshooting (including each retry attempt).
  • Static analysis: A root phpstan.neon.dist (Level 8) ships with the package — mirror it in your project if you extend LastFmClient.

Performance Tips

  • Batch Requests:
    $results = $lastFmClient->batch([
        'getArtistInfo' => ['artist' => 'Arctic Monkeys'],
        'getTopTracks' => ['artist' => 'Arctic Monkeys', 'period' => '7day'],
    ]);
    
  • Caching:
    $cacheKey = 'lastfm_top_artists_' . $period;
    if (!$cached = cache()->get($cacheKey)) {
        $cached = $lastFmClient->getTopArtists($period);
        cache()->put($cacheKey, $cached, now()->addHours(1));
    }
    
    Cache is still cheaper than a successful retry — layer caching in front of retries.

Extension Points

  1. Custom Clients:

    class CustomLastFmClient extends LastFmClient
    {
        public function getArtistTopFans(string $artistName, int $limit = 10): array
        {
            return $this->call('artist.getTopFans', [
                'artist' => $artistName,
                'limit' => $limit,
            ]);
        }
    }
    

    Register as a service:

    services:
        App\Service\CustomLastFmClient:
            arguments:
                $client: '@calliostro_lastfm.client'
    
  2. Middleware:

    $lastFmClient->getMiddlewareStack()->add(
        new AddUserAgentMiddleware('MyApp/1.0')
    );
    
  3. Event Listeners:

    $dispatcher->addListener(LastFmClientEvents::BEFORE_REQUEST, function (BeforeRequestEvent $event) {
        // Log request details (fires once per attempt, including retries)
    });
    

Compatibility

  • v2.1.0 is CI-tested against PHP 8.1–8.6 and Symfony 6.4 LTS, 7.x, 8.0, 8.1, 8.2. Pin Symfony constraints accordingly; PHP 8.0 and below are no longer covered by the matrix — upgrade before relying on retry features.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc