petitpress/gps-messenger-bundle
Laravel bundle for GPS Messenger: send and receive location-based messages, integrate tracking updates, and manage messaging workflows via simple configuration. Designed to drop into existing apps with minimal setup for GPS-enabled notifications and events.
Install the Bundle
composer require petitpress/gps-messenger-bundle google/cloud-pubsub
Add to config/bundles.php:
return [
Petitpress\GpsMessengerBundle\PetitpressGpsMessengerBundle::class => ['all' => true],
];
Configure Google Cloud Credentials
Store your service account JSON key in a secure location (e.g., config/google-credentials.json) and set the environment variable:
export GOOGLE_APPLICATION_CREDENTIALS="%kernel.project_dir%/config/google-credentials.json"
Define a Message Class Create a simple message handler (e.g., for GPS tracking events):
namespace App\Message;
class GpsTrackingEvent
{
public function __construct(
public string $deviceId,
public float $latitude,
public float $longitude,
public \DateTimeImmutable $timestamp
) {}
}
Configure Messenger Transport
Update config/packages/messenger.yaml:
framework:
messenger:
transports:
gps_pubsub:
dsn: "gps://your-project-id/your-topic"
options:
subscription: "your-subscription"
client:
project_id: "your-project-id"
key_file: "%kernel.project_dir%/config/google-credentials.json"
routing:
'App\Message\GpsTrackingEvent': gps_pubsub
Dispatch a Test Message
use App\Message\GpsTrackingEvent;
use Symfony\Component\Messenger\MessageBusInterface;
public function __construct(private MessageBusInterface $bus) {}
public function handleTrackingEvent()
{
$this->bus->dispatch(new GpsTrackingEvent(
'device-123',
37.7749,
-122.4194,
new \DateTimeImmutable()
));
}
Consume Messages Run the Messenger worker:
php bin/console messenger:consume gps_pubsub -vv
Pub/Sub Transport Integration
gps:// DSN format for all Pub/Sub transports.gps://project-id/topic-name?subscription=sub-name.messenger.yaml:
messenger:
transports:
gps_pubsub:
dsn: "gps://..."
retry_strategy:
max_retries: 3
delay: 1000
multiplier: 2
Message Normalization
GpsTrackingEvent objects.namespace App\Middleware;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Messenger\Handler\Middleware\StackInterface;
class NormalizeGpsPayloadMiddleware
{
public function __invoke($message, StackInterface $next)
{
// Custom logic to transform raw GPS data
return $next($message);
}
}
Routing by Message Type
messenger:
routing:
'App\Message\GpsTrackingEvent': gps_pubsub
'App\Message\DeviceAlert': gps_pubsub_alerts
messenger.yaml:
transports:
gps_pubsub:
dsn: "gps://project-id/tracking-topic"
gps_pubsub_alerts:
dsn: "gps://project-id/alerts-topic"
Async Processing with Workers
php bin/console messenger:consume gps_pubsub -vv --limit=10
[program:gps-worker]
command=php /path/to/bin/console messenger:consume gps_pubsub -vv
autostart=true
autorestart=true
Error Handling and Retries
messenger.yaml:
messenger:
failure_transport: failed
transports:
failed:
dsn: "doctrine://default"
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Messenger\MessageBusInterface;
use Google\Cloud\PubSub\PubSubClientInterface;
class PubSubFailureHandler
{
public function __construct(private PubSubClientInterface $pubsub) {}
public function __invoke($failedMessage)
{
// Log or dead-letter Pub/Sub-specific failures
$this->pubsub->publish(...);
}
}
Laravel-Specific Adaptations
$this->app->bind(MessageBusInterface::class, function ($app) {
return $app->make('messenger.bus.default');
});
config/petitpress_gps_messenger.php:
return [
'client' => [
'project_id' => env('GOOGLE_CLOUD_PROJECT'),
'key_file' => env('GOOGLE_APPLICATION_CREDENTIALS'),
],
'transports' => [
'gps_async' => [
'dsn' => 'gps://'.env('GOOGLE_CLOUD_PROJECT').'/'.env('PUBSUB_TOPIC'),
'options' => [
'subscription' => env('PUBSUB_SUBSCRIPTION'),
],
],
],
];
Testing with Local Pub/Sub Emulator
docker run -p 8085:8085 gcr.io/google.com/cloudsdktool/cloud-sdk:latest \
gcloud beta emulators pubsub start --host-port=0.0.0.0:8085
messenger.yaml:
transports:
gps_pubsub:
dsn: "gps://emulator/emulator-topic"
options:
emulator_host: "localhost:8085"
Monitoring and Observability
use Symfony\Component\Messenger\Middleware\HandleMessageMiddleware;
class LoggingMiddleware
{
public function __invoke($message, StackInterface $next)
{
\Log::info('Message dispatched', ['message' => get_class($message)]);
return $next($message);
}
}
Serverless Deployment (Cloud Functions)
# cloudbuild.yaml
steps:
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
args: ['gcloud', 'functions', 'deploy', 'gps-worker',
'--runtime', 'php81',
'--trigger-topic', 'your-topic',
'--entry-point', 'handlePubSubMessage']
use Google\Cloud\PubSub\PubSubMessage;
function handlePubSubMessage(PubSubMessage $message) {
$data = json_decode($message->data(), true);
// Dispatch to Laravel Messenger via HTTP or direct SDK call
}
Authentication Issues
Google\Auth\Exception\InvalidCredentialsException if credentials are invalid or expired.GOOGLE_APPLICATION_CREDENTIALS points to a valid JSON key file.Message Serialization Errors
SerializationException.__serialize()/`__unserializeHow can I help you explore Laravel packages today?