zbox/unified-push
Unified push notification package for Laravel that sends messages through multiple providers behind one clean API. Configure your drivers, target devices or topics, and deliver consistent push notifications without rewriting provider-specific code.
src/. Open composer.json first and check the illuminate/* and php constraints — a 2016 release will target Laravel 5.2/5.3-era APIs and PHP 5.6/7.0. Verify it will actually install against your app before planning around it.extra.laravel in composer.json declares discovery. In a legacy config/app.php, add the provider under providers and any facade under aliases. Then publish the config (php artisan vendor:publish --provider="Zbox\UnifiedPush\...ServiceProvider") and read every key: APNS certificate path/passphrase and sandbox flag, GCM API key, MPNS credentials, and any default driver selection..env and resolve them inside config/unified-push.php only — never call env() from your own code, or config:cache will silently return null. Keep .pem/.p12 files outside the web root (e.g. storage/app/push/) and confirm the PHP process can read them.php artisan tinker to one real device token, one platform at a time. For APNS, confirm you are pointed at the sandbox gateway and using a sandbox provisioning profile; most first-run failures are environment/token mismatches, not package bugs. Once a single send succeeds, immediately wrap it in a queued job — do not call the package from a controller.push_tokens table with user_id, platform (ios/android/windows), app/tenant, token, last_seen_at, and a unique index on (platform, token) prevents the duplicate sends and cross-environment token reuse that plague these integrations. Accept token registration from the client via an authenticated endpoint and upsert, don't insert.PushSender with send(DeviceToken $token, PushMessage $message): PushResult, implement it with this package, and bind it in a service provider. This gives you one place to normalize per-platform payloads, one place to log, and a clean migration path when the underlying protocols need replacing.aps envelope (alert, badge, sound, content-available); GCM distinguishes notification messages from data-only messages; MPNS uses its own XML/tile/toast format. Don't try to force one generic array through all three — have a PushMessage value object and per-driver serializers.SendPushNotification job with $tries, backoff(), and chunk() on token collections (500–1000 per batch). Old APNS binary transports typically open a connection per send or per batch, so unbounded loops will stall workers. Set explicit connect/read timeouts on the underlying HTTP client where configurable.NotificationChannel that resolves device tokens for the notifiable and delegates to your PushSender keeps push logic in app/Notifications and out of domain services. Keep the raw package calls out of Notification classes.NotRegistered/InvalidRegistration responses (and canonical ID remapping) should mark tokens inactive or update them. Schedule a pruning command and a feedback-poll command, and never delete on a single ambiguous error — only on explicit unrecoverable responses.PushSender contract so swapping to APNS HTTP/2 and FCM HTTP v1 is a one-class change.each(), missing return types) and Laravel container/contract changes. Pin the exact version, run the test suite or a smoke script on your target PHP, and check whether the package's dependencies are themselves abandoned. MIT licensing means forking and patching is viable if you must keep it.BadDeviceToken, Unregistered), expired certificates, wrong bundle ID/team ID, and GCM keys scoped to the wrong project all look like code failures. Build a push:diagnose {token} artisan command that prints the resolved driver, endpoint, and credential fingerprint.json_encode(..., JSON_UNESCAPED_UNICODE) and guard against malformed UTF-8 from user-generated content. For APNS, content-available: 1 silent pushes are throttled and must not include an alert.config:cache, relative certificate paths resolve differently depending on the working directory. Always use storage_path()/base_path() in the config file. Check file permissions when running under www-data or in containers, and mount certificates as secrets rather than baking them into images.extend()/driver-registration hook, use it to add FCM or a mock driver for tests. If not, wrap at your PushSender boundary and inject a fake in unit tests — do not hit real gateways in CI. Keep one integration test per platform against sandbox credentials, gated by an environment flag.How can I help you explore Laravel packages today?