hans-peter-ording / fantasypros-api-symfony-bundle
Symfony bundle to import NFL data from the FantasyPros public API into Doctrine entities via Symfony Messenger.
Package info
github.com/HansPeterOrding/fantasypros-api-symfony-bundle
Type:symfony-bundle
pkg:composer/hans-peter-ording/fantasypros-api-symfony-bundle
Requires
- php: >=8.4
- hans-peter-ording/fantasypros-api-client: ^0.1|dev-main
- symfony/config: ^7.0|^8.0
- symfony/console: ^7.0|^8.0
- symfony/dependency-injection: ^7.0|^8.0
- symfony/event-dispatcher: ^7.0|^8.0
- symfony/http-kernel: ^7.0|^8.0
- symfony/messenger: ^7.0|^8.0
- symfony/orm-pack: ^2.0
Requires (Dev)
- symfony/maker-bundle: ^1.0@dev
- symfony/phpunit-bridge: ^7.0|^8.0
Suggests
- guzzlehttp/guzzle: Popular PSR-18 HTTP client implementation
- nyholm/psr7: Lightweight PSR-17 request/URI factory implementation, commonly paired with Guzzle
- php-http/discovery: Enables zero-config auto-discovery of PSR-18 clients and PSR-17 factories
- symfony/http-client: PSR-18 client and PSR-17 factories in one package, usable via Psr18Client
README
Symfony bundle to import NFL data from the FantasyPros public API into your database. Built on top of fantasypros-api-client.
Package contains:
- Doctrine entities for FantasyPros resources (players, rankings, consensus rankings, experts, projections, news, injuries)
- Converters and batch importers (one API request maps to one bulk upsert)
- Symfony Messenger messages and handlers (one message = one API request)
- Post-import Symfony events for consumer integration
- Sync and prune console commands
The bundle is deliberately rate-limit agnostic: scheduling, request budgets, and quota enforcement are the consumer's responsibility (e.g. via a PSR-18 decorator around the injected HTTP client). This keeps the bundle usable for any FantasyPros subscription tier.
Installation
composer require hans-peter-ording/fantasypros-api-symfony-bundle
Register the bundle manually (no Flex recipe):
// config/bundles.php return [ // ... HansPeterOrding\FantasyProsApiSymfonyBundle\HpoFantasyProsApiSymfonyBundle::class => ['all' => true], ];
Register the Doctrine mapping:
# config/packages/doctrine.yaml doctrine: orm: mappings: HpoFantasyProsApiSymfonyBundle: type: attribute dir: '%kernel.project_dir%/vendor/hans-peter-ording/fantasypros-api-symfony-bundle/src/Entity' prefix: 'HansPeterOrding\FantasyProsApiSymfonyBundle\Entity' alias: 'HpoFantasyProsApiSymfony'
Provide your API key and generate the schema:
# .env.local / your secret store FANTASYPROS_API_KEY=your-key php bin/console make:migration # review, then migrate php bin/console doctrine:migrations:migrate
Copy and adapt the Messenger transports:
cp vendor/hans-peter-ording/fantasypros-api-symfony-bundle/messenger.yaml.dist \ config/packages/messenger.yaml
Usage
Dispatch syncs via the console commands (each dispatches one or more async messages; one message equals exactly one API request):
php bin/console fp:sync:players php bin/console fp:sync:ranking-board 2026 --week=0 php bin/console fp:sync:consensus 2026 DRAFT STD RB php bin/console fp:sync:consensus-matrix 2026 DRAFT DYNASTY ROOKIES ADP php bin/console fp:sync:projections 2026 RB --week=1 php bin/console fp:sync:experts 2026 php bin/console fp:sync:news --limit=50 php bin/console fp:sync:injuries 2026 --week=1 php bin/console fp:ranking-snapshots:prune --keep-days=400
fp:sync:consensus-matrix expands each ranking type into the request-minimal slice set (STD for all positions, PPR/HALF only for reception positions - the API returns identical data for the rest). After every import a dedicated event (FpPlayersImportedEvent, FpConsensusRankingImportedEvent, ...) is dispatched carrying the message and an FpImportResult, so the consuming application can chain follow-up work (crosswalk matching, cache invalidation, metrics).
Enforcing a request budget
Replace the HTTP client the bundle's API client uses with your own counting/limiting PSR-18 decorator:
# config/services.yaml (consuming application) HansPeterOrding\FantasyProsApiClient\ApiClient\FantasyProsApiClientInterface: factory: ['@HansPeterOrding\FantasyProsApiClient\ApiClient\FantasyProsApiClientFactory', 'getFantasyProsApiClient'] arguments: $apiKey: '%env(FANTASYPROS_API_KEY)%' $client: '@App\Http\BudgetGuardedFantasyProsHttpClient'
When the guard refuses a request (or FantasyPros answers 429), handlers log a warning and rethrow TooManyRequestsException - your Messenger retry strategy decides what happens next.
Documentation
Documentation for FantasyProsApiSymfonyBundle can be found at Read the docs
License
This bundle is released under the MIT license. See the included LICENSE file for more information.