Installation Add the bundle to your Symfony project via Composer:
composer require ciricihq/api-bundle
Enable the bundle in config/bundles.php:
return [
// ...
CiriciHQ\ApiBundle\ApiBundle::class => ['all' => true],
];
Configuration Publish the default configuration:
php bin/console ciricihq:api:install
Update config/packages/ciricihq_api.yaml with your Firebase/APNs credentials (or other push providers).
First Use Case: Sending a Push Notification
Inject the PushNotificationService and send a test notification:
use CiriciHQ\ApiBundle\Service\PushNotificationService;
class MyController extends AbstractController
{
public function sendNotification(PushNotificationService $pushService): Response
{
$result = $pushService->send(
'device_token_here',
[
'title' => 'Hello!',
'body' => 'This is your first push notification.',
]
);
return $this->json($result);
}
}
Sending Notifications
$pushService->send(
'device_token',
['title' => 'Alert', 'body' => 'New message'],
['priority' => 'high', 'data' => ['key' => 'value']]
);
$pushService->sendBatch([
'token1' => ['title' => 'Batch 1'],
'token2' => ['title' => 'Batch 2'],
]);
Handling Responses
$result->isSuccess() for success/failure.$result->getResponse().Provider-Specific Logic
AbstractPushProvider to support custom providers (e.g., WebPush, custom HTTP APIs).Symfony Messenger Integration
Use the PushNotificationMessage class to queue notifications:
$message = new PushNotificationMessage(
'device_token',
['title' => 'Queued', 'body' => 'Delayed push']
);
$bus->dispatch($message);
Configure the transport in config/packages/messenger.yaml:
transports:
push_notifications: { dsn: 'sync://' }
Event Listeners
Subscribe to PushNotificationSentEvent to log or modify payloads:
use CiriciHQ\ApiBundle\Event\PushNotificationSentEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class PushLogger implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [PushNotificationSentEvent::class => 'log'];
}
public function log(PushNotificationSentEvent $event): void
{
// Custom logic (e.g., logging, analytics)
}
}
Token Validation
device_token format before sending (e.g., regex for Firebase/APNs tokens).if (!preg_match('/^[a-zA-Z0-9\-_]{1,}$/', $token)) {
throw new \InvalidArgumentException('Invalid token format.');
}
Rate Limiting
$pushService->sendWithRetry($token, $payload, 3); // Retry 3 times
Configuration Overrides
%env% or parameter bags:
# config/packages/ciricihq_api.yaml
ciricihq_api:
providers:
firebase:
project_id: '%env(FIREBASE_PROJECT_ID)%'
Enable Verbose Logging
Set debug: true in config to log raw API responses:
ciricihq_api:
debug: true
Check logs at var/log/dev.log.
Mock Providers for Testing
Create a test provider by extending AbstractPushProvider and overriding send() to return mock responses:
class MockPushProvider extends AbstractPushProvider
{
public function send(string $token, array $payload): PushResponse
{
return new PushResponse(true, ['mock' => 'response']);
}
}
Bind it in services.yaml:
services:
CiriciHQ\ApiBundle\Service\PushNotificationService:
arguments:
$provider: '@mock_push_provider'
Custom Payload Transformers
Override PayloadTransformerInterface to modify payloads before sending:
class CustomTransformer implements PayloadTransformerInterface
{
public function transform(array $payload): array
{
$payload['custom_key'] = 'custom_value';
return $payload;
}
}
Register it in services.yaml:
services:
CiriciHQ\ApiBundle\Transformer\PayloadTransformerInterface: '@custom_transformer'
Async Processing For high-volume apps, offload to a queue (e.g., RabbitMQ, Redis):
# config/packages/messenger.yaml
transports:
push_notifications: { dsn: '%env(MESSENGER_TRANSPORT_DSN)%' }
routing:
'CiriciHQ\ApiBundle\Message\PushNotificationMessage': push_notifications
Webhook Validation If using APNs HTTP/2 or Firebase’s webhook, validate signatures:
use CiriciHQ\ApiBundle\Validator\WebhookValidator;
$validator = new WebhookValidator($request->getContent());
if (!$validator->isValid($request->headers->get('auth-key'))) {
throw new \RuntimeException('Invalid webhook signature.');
}
How can I help you explore Laravel packages today?