brozot / Laravel-FCM

Laravel-FCM is an easy to use package working with both Laravel and Lumen for sending push notification with Firebase Cloud Messaging (FCM).
MIT License
888 stars 406 forks source link

Feature request: Notification service #19

Open MithrandirDK opened 7 years ago

MithrandirDK commented 7 years ago

I would like to use FCM in Laravel Notifications and while I found https://github.com/douglasresendemaciel/fcm-laravel-notification that has that part, I found this project to be better for building the actual Push Notification.

I can give it a go in trying to build a wrapper around your Data/Notification/Options classes, unless you have already thought about going that way?

brozot commented 7 years ago

Hello,

Thank you for your interest about this package. I have planned to explore a way to make this package compatible with Laravel Notifications. If you want to work on that we can collaborate.

Best regards

MithrandirDK commented 7 years ago

I have created a NotificationServiceProvider and related classes in my own namespace, but it should be possible to move directly.

I have made a wrapper around the options and payload classes to make it possible for a toFCM() method on the notification to return a complete message, ready to be sent. I added helper methods to dispatch options, notification and data to the various builders, but maybe it is just as good to have $message->options->setTimeToLive($value) rather than $message->setOption('timeToLive', $value)?

In the FirebaseChannel::send() method, I chose to add the notification's toArray() result as payload data, because in my use cases, it seems to be a general desire - but maybe we should leave that up to the toFCM() method to decide?

NotificationServiceProvider.php

<?php

namespace App\Providers;

use App\Notifications\Channels\FirebaseChannel;
use Illuminate\Notifications\ChannelManager;
use Illuminate\Support\ServiceProvider;

/**
 * Class NotificationServiceProvider
 * @package DouglasResende\FCM
 */
class NotificationServiceProvider extends ServiceProvider
{
    /**
     * Register
     */
    public function register()
    {
        $app = $this->app;
        $this->app->make(ChannelManager::class)->extend('fcm', function() use ($app) {
            return $app->make(FirebaseChannel::class);
        });
    }
}

FirebaseChannel (for channeling notification messages)

<?php

namespace App\Notifications\Channels;

use App\Notifications\Contracts\FirebaseNotification;
use Illuminate\Contracts\Config\Repository as Config;
use Illuminate\Notifications\Notifiable;

/**
 * Class FirebaseChannel
 */
class FirebaseChannel
{
    /**
     * @var Config
     */
    private $config;

    /**
     * FirebaseChannel constructor.
     * @param Config $config
     */
    public function __construct(Config $config)
    {
        $this->config = $config;
    }

    /**
     * @param Notifiable $notifiable
     * @param \App\Notifications\Contracts\FirebaseNotification $notification
     */
    public function send(Notifiable $notifiable, FirebaseNotification $notification)
    {
        $message = $notification->toFCM($notifiable);
        $message->setTo($notifiable->routeNotificationFor('fcm'));

        $message->addData($notification->toArray());

        $message->send();

    }

}

FirebaseMessage

<?php

namespace App\Notifications\Messages;

use LaravelFCM\Facades\FCM;
use LaravelFCM\Message\OptionsBuilder;
use LaravelFCM\Message\PayloadDataBuilder;
use LaravelFCM\Message\PayloadNotificationBuilder;

class FirebaseMessage
{
    /**
     * @var OptionsBuilder
     */
    protected $optionsBuilder;
    /**
     * @var PayloadNotificationBuilder
     */
    protected $notificationBuilder;
    /**
     * @var PayloadDataBuilder
     */
    protected $dataBuilder;
    /**
     * @var array
     */
    protected $to = [];

    public function __construct()
    {
        $this->optionsBuilder = new OptionsBuilder();
        $this->notificationBuilder = new PayloadNotificationBuilder();
        $this->dataBuilder = new PayloadDataBuilder();
    }

    /**
     * Set value on OptionsBuilder
     * @param $key
     * @param $value
     *
     * @return $this
     */
    public function setOption($key, $value) {
        $method = 'set' . ucfirst($key);
        $this->optionsBuilder->$method($value);

        return $this;
    }

    public function setNotification($key, $value) {
        $method = 'set' . ucfirst($key);
        $this->notificationBuilder->$method($value);

        return $this;
    }

    public function addData(array $data) {
        $this->dataBuilder->addData($data);

        return $this;
    }

    /**
     * Add a FCM token to the recipients list
     *
     * @param $token
     */
    public function setTo($token) {
        $this->to[] = $token;
    }

    /**
     * Send notification to FCM
     */
    public function send() {
        $downstreamResponse = FCM::sendTo($this->to, $this->optionsBuilder->build(), $this->notificationBuilder->build(), $this->dataBuilder->build());
    }
}

And finally, the interface declaring the toFCM method

<?php
namespace App\Notifications\Contracts;

use App\Notifications\Messages\FirebaseMessage;
use Illuminate\Contracts\Support\Arrayable;

/**
 * Interface FirebaseNotification
 */
interface FirebaseNotification extends Arrayable
{
    /**
     * @param $notifiable
     * @return FirebaseMessage
     */
    public function toFCM($notifiable);

}

Let me know what you think.

brozot commented 7 years ago

Hi sorry to answer only now

It looks good,

I will take a look more in detail tomorrow.

Thank you very much

tusharvikky commented 7 years ago

Any update on this?

prasanthsd commented 7 years ago

Are there any updates on this? This is one of the must have features

francislavoie commented 6 years ago

+1 from me as well.

I was looking at the docs, and the way the lib is currently set up doesn't make a whole lot of sense for me, from a user perspective. You have a FCM facade, but to be able to use it you still need to use the builders, which pretty much counteracts the entire point of facades. You get trapped into a single implementation. The FCM facade (or FirebaseMessage as defined in a comment above) should wrap the builders so that they "could" be swapped out. It also makes writing code much nicer, no longer need to create a bunch of builders before actually sending messages, it just gets simplified into ->setOption() calls etc. I think this really a must-have for this lib to make is actually nice to use. The functionality is great, but usage can be significantly cleaned up.

mpyw commented 6 years ago

+1

Need updates

chimit commented 4 years ago

Still waiting for Laravel Notifications support.

walidbagh commented 4 years ago

@brozot Hey, any news on this ?