adeelnawaz/polr-api-bundle
Symfony 4/5 bundle wrapping adeelnawaz/polr-api-client to integrate the Polr URL shortener REST API. Provides a PolrApiService for calling endpoints with DTOs, supports API quota throttling, and throws ApiResponseException on failures.
Install the Bundle Run:
composer require adeelnawaz/polr-api-bundle
Configure the Bundle
Create config/packages/polr_api.yml (Symfony 5+) or config/polr_api.yml (Symfony 4):
polr_api:
api_url: '%env(POLR_API_URL)%'
api_key: '%env(POLR_API_KEY)%'
api_quota: '%env(int:POLR_API_QUOTA)%'
Add .env variables:
POLR_API_URL=https://your-polr-instance.com/api
POLR_API_KEY=your_api_key_here
POLR_API_QUOTA=100 # Adjust based on Polr's rate limits
First API Call
Inject PolrApiService into a controller or service and use it:
use AdeelNawaz\PolrApiBundle\Service\PolrApiService;
class MyController extends AbstractController
{
public function __construct(private PolrApiService $polrApi)
{
}
public function index()
{
$links = $this->polrApi->getLinks();
return $this->json($links);
}
}
PolrApiService mirrors the underlying polr-api-client methods (e.g., getLinks(), createLink(), deleteLink()).$links = $this->polrApi->getLinks(['per_page' => 10]);
$newLink = $this->polrApi->createLink([
'title' => 'My Shortened Link',
'url' => 'https://example.com/long-url',
]);
$this->polrApi->deleteLink($linkId);
api_quota in polr_api.yml to respect Polr’s rate limits (e.g., api_quota: 60 for 60 calls/minute).PolrApiException with quota-related messages.try-catch to handle exceptions:
try {
$link = $this->polrApi->getLink($id);
} catch (\AdeelNawaz\PolrApiBundle\Exception\PolrApiException $e) {
$this->addFlash('error', $e->getMessage());
return $this->redirectToRoute('home');
}
PolrApiService directly (as shown above).class LinkManager
{
public function __construct(private PolrApiService $polrApi) {}
public function shortenUrl(string $url, string $title): array
{
return $this->polrApi->createLink(compact('url', 'title'));
}
}
config/packages/polr_api.yml:
polr_api:
api_url: '%env(POLR_CUSTOM_URL)%' # Override per environment
api_quota: 30
PolrApiService in PHPUnit:
$this->createMock(PolrApiService::class)
->method('getLinks')
->willReturn([['id' => 1, 'title' => 'Test']]);
Symfony Forms Use the bundle to validate or fetch data for forms:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('url', TextType::class, [
'constraints' => [
new Callback([$this->polrApi, 'validateUrl']),
],
]);
}
Event Listeners Trigger actions after link creation/deletion:
public function onLinkCreated(LinkEvent $event)
{
$this->polrApi->updateLink($event->getLinkId(), ['notes' => 'Auto-generated']);
}
Command-Line Tools Create a Symfony command to manage links:
class PolrLinkCommand extends Command
{
protected function execute(InputInterface $input, OutputInterface $output)
{
$links = $this->polrApi->getLinks();
foreach ($links as $link) {
$output->writeln($link['title'] . ': ' . $link['url']);
}
}
}
Caching Responses Cache frequent API calls (e.g., fetching all links):
$links = $this->cache->get('polr_links', function () {
return $this->polrApi->getLinks();
}, 300); // Cache for 5 minutes
Quota Mismatch
api_quota is set lower than Polr’s actual limit, you’ll hit artificial delays or errors. Set it to 0 for no delay (unlimited) or match Polr’s documented rate limit (e.g., 60 for 60 calls/minute).API Key Permissions
read:links, write:links). Invalid keys throw PolrApiException with HTTP 403/401.Endpoint Changes
polr-api-client, which may lag behind Polr’s API updates. Check the Polr API changelog and update the underlying package if needed:
composer require adeelnawaz/polr-api-client:dev-main
Symfony Version Conflicts
Environment Variables
POLR_API_URL or POLR_API_KEY in .env will throw a RuntimeException during service compilation. Validate with:
php bin/console debug:container | grep polr
Enable Debug Mode
Set POLR_API_DEBUG=true in .env to log raw API responses:
polr_api:
debug: '%env(bool:POLR_API_DEBUG)%'
Check HTTP Status Codes Exceptions include the HTTP status code. Example:
catch (PolrApiException $e) {
if ($e->getCode() === 404) {
// Handle "Link not found"
}
}
Network Issues
https://your-polr-instance.com/api).Extend the Service Create a decorator to add custom logic:
class CustomPolrApiService extends PolrApiService
{
public function getLinksWithStats()
{
$links = parent::getLinks();
return array_map(function ($link) {
$link['stats'] = $this->fetchLinkStats($link['id']);
return $link;
}, $links);
}
}
Register it in services.yaml:
services:
AdeelNawaz\PolrApiBundle\Service\PolrApiService:
class: App\Service\CustomPolrApiService
Use DTOs for Responses Map API responses to PHP objects for type safety:
class LinkDto
{
public function __construct(
public string $id,
public string $title,
public string $url,
) {}
How can I help you explore Laravel packages today?