Skip to content

backend-2022/pushify

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

4 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Pushify

Latest Version on Packagist PHP Version Laravel Version License: MIT

Laravel backend package for sending push notifications through one selected provider at a time.

Supported providers:

Provider Scheduling
πŸ”₯ Firebase Cloud Messaging (FCM) Via scheduled command
πŸ“£ OneSignal Native send_after

Project Structure

pushify/
β”œβ”€β”€ config/
β”‚   └── pushify.php
β”œβ”€β”€ database/
β”‚   └── migrations/
β”‚       └── 2026_01_01_000000_create_pushify_notifications_table.php
β”œβ”€β”€ routes/
β”‚   └── pushify.php
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ Commands/
β”‚   β”‚   └── SendScheduledPushifyNotifications.php
β”‚   β”œβ”€β”€ Contracts/
β”‚   β”‚   β”œβ”€β”€ PushifyProviderInterface.php
β”‚   β”‚   └── PushifyServiceInterface.php
β”‚   β”œβ”€β”€ Factories/
β”‚   β”‚   └── PushifyProviderFactory.php
β”‚   β”œβ”€β”€ Http/
β”‚   β”‚   β”œβ”€β”€ Controllers/
β”‚   β”‚   β”‚   └── PushifyController.php
β”‚   β”‚   β”œβ”€β”€ Requests/
β”‚   β”‚   β”‚   └── StorePushifyRequest.php
β”‚   β”‚   └── Resources/
β”‚   β”‚       └── PushifyResource.php
β”‚   β”œβ”€β”€ Models/
β”‚   β”‚   └── Pushify.php
β”‚   β”œβ”€β”€ Providers/
β”‚   β”‚   β”œβ”€β”€ FirebaseProvider.php
β”‚   β”‚   └── OneSignalProvider.php
β”‚   β”œβ”€β”€ Services/
β”‚   β”‚   β”œβ”€β”€ FirebaseService.php
β”‚   β”‚   β”œβ”€β”€ OneSignalService.php
β”‚   β”‚   └── PushifyService.php
β”‚   └── PushifyServiceProvider.php
β”œβ”€β”€ stubs/
β”‚   β”œβ”€β”€ Http/
β”‚   β”‚   β”œβ”€β”€ Controllers/
β”‚   β”‚   β”‚   └── PushifyController.stub
β”‚   β”‚   β”œβ”€β”€ Requests/
β”‚   β”‚   β”‚   └── StorePushifyRequest.stub
β”‚   β”‚   └── Resources/
β”‚   β”‚       └── PushifyResource.stub
β”‚   └── routes/
β”‚       └── pushify.stub
└── composer.json

Table of Contents


Requirements

  • PHP >= 8.2
  • Laravel >= 12.0
  • OpenSSL PHP extension (required for Firebase JWT signing β€” no external Google SDK needed)

Installation

composer require badawy24/pushify

Then clear the cache:

php artisan optimize:clear

Publish

Publish everything at once

php artisan vendor:publish --tag=pushify

This publishes only the files you are expected to edit:

config/pushify.php
routes/pushify.php
app/Http/Controllers/Pushify/PushifyController.php
app/Http/Requests/Pushify/StorePushifyRequest.php
app/Http/Resources/Pushify/PushifyResource.php

Core services, providers, factories, models, commands, and contracts stay inside the package and are never published.

Publish separately

# Config only
php artisan vendor:publish --tag=pushify-config

# Routes only
php artisan vendor:publish --tag=pushify-routes

# Controller, Request, Resource
php artisan vendor:publish --tag=pushify-http

Migration

php artisan migrate

Creates the pushify_notifications table:

id, title, body, image, data, scheduled_at,
status, sent_at, failed_at, error_message,
created_at, updated_at

Configuration

Published config file: config/pushify.php

Only one provider is active at a time, selected from .env.

πŸ”₯ Firebase

PUSHIFY_PROVIDER=firebase
FIREBASE_CREDENTIALS=storage/firebase/firebase.json

Place your Firebase service account JSON file at storage/firebase/firebase.json.

Firebase sends to a topic β€” default is all. Configure it in the published config:

'firebase' => [
    'topic' => 'all',
],

Your mobile app must subscribe devices to the same topic.

πŸ“£ OneSignal

PUSHIFY_PROVIDER=onesignal
ONESIGNAL_APP_ID=your-app-id
ONESIGNAL_API_KEY=your-api-key
ONESIGNAL_API_URL=https://api.onesignal.com/notifications

OneSignal sends to included_segments => ['All'].

Optional

# Log full request payload β€” disable in production
PUSHIFY_LOG_PAYLOAD=false

# Disable package routes if you prefer to define your own
PUSHIFY_ROUTES_ENABLED=true

# Change the route prefix (default: pushify)
PUSHIFY_ROUTE_PREFIX=pushify

Routes

The package registers these routes automatically:

GET  /pushify                  List all notifications (paginated)
POST /pushify                  Create and send
GET  /pushify/{pushify}        Show one
POST /pushify/{pushify}/send   Send an existing notification

Check registered routes:

php artisan route:list | grep pushify

Adding Auth Middleware

After publishing, open routes/pushify.php and update the middleware:

Route::prefix(config('pushify.routes.prefix', 'pushify'))
    ->middleware(['api', 'auth:sanctum'])
    ->group(function () {
        // routes...
    });

Usage

Inject the service interface

use Badawy\Pushify\Contracts\PushifyServiceInterface;

The package binds this interface automatically β€” no manual binding required.


Send immediately

use Badawy\Pushify\Contracts\PushifyServiceInterface;

class OfferController extends Controller
{
    public function notify(PushifyServiceInterface $push)
    {
        $notification = $push->sendToAll(
            title: 'New offer',
            body: 'Check our latest offers now',
            data: [
                'type'     => 'offer',
                'offer_id' => 15,
            ],
            image: 'https://example.com/image.jpg',
            scheduledAt: null,
        );

        return response()->json($notification);
    }
}

Both Firebase and OneSignal send immediately when scheduledAt is null.


Schedule a notification

$notification = $push->sendToAll(
    title: 'Upcoming sale',
    body: 'Our sale starts in one hour',
    data: ['type' => 'sale'],
    image: null,
    scheduledAt: now()->addHour()->toDateTimeString(),
);
Provider Behavior
πŸ”₯ Firebase Saved as pending β€” sent by the command when scheduled_at <= now()
πŸ“£ OneSignal Submitted immediately with native send_after β€” OneSignal handles the delay

Create only (without sending)

$notification = $push->create([
    'title'        => 'Draft notification',
    'body'         => 'Notification body',
    'data'         => ['type' => 'general'],
    'image'        => null,
    'scheduled_at' => null,
]);

Saved as pending. Nothing is sent until you manually call send() or run the command.


Send an existing notification

use Badawy\Pushify\Models\Pushify;

$notification = Pushify::findOrFail($id);
$notification = $push->send($notification);

Quick test via Tinker

php artisan tinker
app(\Badawy\Pushify\Contracts\PushifyServiceInterface::class)
    ->sendToAll(
        title: 'Hello',
        body: 'Test from Tinker',
        data: ['type' => 'test'],
        image: null,
        scheduledAt: null,
    );

Available interface methods

// Store a notification record without sending
public function create(array $payload): Pushify;

// Create and send (or schedule) in one call
public function sendToAll(
    string $title,
    string $body,
    array $data = [],
    ?string $image = null,
    ?string $scheduledAt = null
): Pushify;

// Send an existing stored notification
public function send(Pushify $notification): Pushify;

// Mark due OneSignal scheduled notifications as sent locally
public function markScheduledAsSent(): int;

Notification Statuses

Status Meaning
pending Stored, not sent yet
processing Currently being dispatched to the provider
scheduled Submitted to OneSignal with a future send_after
sent Successfully delivered to the provider
failed Failed β€” see error_message column in the database

Scheduled Command

php artisan pushify:send-scheduled
Provider What it does
πŸ”₯ Firebase Sends all pending notifications where scheduled_at <= now()
πŸ“£ OneSignal Marks all scheduled notifications where scheduled_at <= now() as sent locally β€” OneSignal already delivered them

Add to Laravel Scheduler

In routes/console.php:

Schedule::command('pushify:send-scheduled')->everyMinute();

Or via cron:

* * * * * php /path/to/project/artisan pushify:send-scheduled >> /dev/null 2>&1

Customizing the HTTP Layer

After publishing with --tag=pushify-http, you can freely edit:

File Purpose
app/Http/Controllers/Pushify/PushifyController.php Request handling & response
app/Http/Requests/Pushify/StorePushifyRequest.php Validation rules & authorization
app/Http/Resources/Pushify/PushifyResource.php JSON output shape

The published controller injects PushifyServiceInterface β€” extend or replace any logic without touching the package internals.


Adding a Custom Provider

Step 1 β€” Create your provider class:

namespace App\Pushify\Providers;

use Badawy\Pushify\Contracts\PushifyProviderInterface;

class CustomProvider implements PushifyProviderInterface
{
    public function sendToAll(
        string $title,
        string $body,
        array $data = [],
        ?string $image = null,
        ?string $scheduledAt = null
    ): array {
        // Your HTTP call or SDK integration here
        return ['success' => true];
    }
}

Step 2 β€” Register it in config/pushify.php:

'providers' => [
    'firebase'  => \Badawy\Pushify\Providers\FirebaseProvider::class,
    'onesignal' => \Badawy\Pushify\Providers\OneSignalProvider::class,
    'custom'    => \App\Pushify\Providers\CustomProvider::class,
],

Step 3 β€” Activate it in .env:

PUSHIFY_PROVIDER=custom

Store Endpoint Payload

POST /pushify

{
    "title": "New offer",
    "body": "Check our latest offers",
    "image": "https://example.com/image.jpg",
    "data": {
        "type": "offer",
        "offer_id": 15
    },
    "scheduled_at": null
}

Scheduled example:

{
    "title": "Scheduled offer",
    "body": "This will be sent later",
    "image": null,
    "data": { "type": "offer" },
    "scheduled_at": "2026-06-01 09:00:00"
}

Response Structure

All endpoints return a consistent JSON envelope:

{
    "data": {
        "id": 1,
        "title": "New offer",
        "body": "Check our latest offers",
        "image": "https://example.com/image.jpg",
        "data": { "type": "offer", "offer_id": "15" },
        "scheduled_at": null,
        "status": "sent",
        "sent_at": "2026-01-01T12:00:00+00:00",
        "failed_at": null,
        "created_at": "2026-01-01T11:59:00+00:00",
        "updated_at": "2026-01-01T12:00:00+00:00"
    }
}

Authors

Badawy Β· Hassan


License

MIT

About

A powerful Laravel package for sending push notifications via multiple providers like Firebase and OneSignal with a clean, extensible architecture.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages