如何使用Laravel 5.2发送通知

时间:2016-12-13 05:01:08

标签: laravel events notifications queue

我有一个工作网站,用户可以关注公司,然后他会在新工作时收到通知,所以我做的是以下内容:

我创建了一个名为JobNotification的模型,每当公司创建新工作时,我创建一个工作通知,我存储company_id,job_id和生成的文本,因此这个工作通知将被发送给用户,

我接下来要做的是创建一个名为SendJobNotification的作业,并在创建JobNotification后调度它,SendJobNotification将获取跟随该公司的用户并插入user_id和job_notification_id,这样当用户再次登录时,他将会看到通知。

所以问题是,还有更好的方法吗?也许使用事件? 我不想使用队列:在服务器中监听以运行队列,用户提取也需要花费很多时间。 这是我的SendJobNotification工作代码:

namespace App\Jobs;
use App\AccountJobNotification;
use App\Jobs\Job;
use App\Account;
use App\JobNotification;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Company;
class SendJobNotification extends Job implements ShouldQueue
{
    use InteractsWithQueue, SerializesModels;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    protected $notification;

    public function __construct(JobNotification $notification)
    {
        $this->notification = $notification;

    }  
    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $users = Company::find($this->notification->company_id)->followers()->get();
        foreach ($users as $user)
        {
            $job_notification = new AccountJobNotification();
            $job_notification->user_id = $user->id;
            $job_notification->job_notification_id = $this->notification->id;
            $job_notification->save();
        }


    }
}

请注意,我不是在做实时通知。

3 个答案:

答案 0 :(得分:3)

是的,你可以通过使用事件和监听器来实现。 我会这样做:
在您的控制器中,触发事件:

   Event::fire(new JobCreated($job));

然后添加一个事件(JobCreated.php)和一个监听器(AddNotifications.php):

在您的事件文件夹中创建:JobCreated.php:

<?php

namespace App\Events;

use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class JobCreated extends Event
{
    public function __construct($job)
    {
        $this->job_id=$job->id;
        $this->company_id=$job->company_id;
    }
}

在您的侦听器文件夹中,创建Addnotifications.php:

<?php

namespace App\Listeners;

use App\Events\JobCreated;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class AddNotifications
{
    public function handle(JobCreated $event)
    {
        $company_id=$event->company_id;
        $job_id=$event->job_id;
        your handle code......
    }
}

不要忘记将两者都包含在providers文件夹中的EventServiceProvider.php中:

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        'App\Events\JobCreated' => [
            'App\Listeners\AddNotifications'
        ],
    ];
}

答案 1 :(得分:2)

@Ferran的回答是正确的。要在队列中添加此事件,您必须实现如下所示的ShouldQueue接口。

 <?php

    namespace App\Events;

    use App\Events\Event;
    use Illuminate\Queue\SerializesModels;
    use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
    use Illuminate\Contracts\Queue\ShouldQueue;


    class JobCreated extends Event implements ShouldQueue
    {
        public function __construct($job)
        {
            $this->job_id=$job->id;
            $this->company_id=$job->company_id;
        }
    }

有效地运行队列。使用queue :: work as并将其作为守护进程运行,如下所示

php artisan queue:work connection-name --daemon

在linux架构上添加&#34;&gt; / dev / null 2&gt;&amp; 1&#34;在结束代码命令,无需等待即可运行它。

php artisan queue:work beanstalkd --sleep=3 --tries=3 --daemon > /dev/null 2>&1 & 

这里beanstalkd是队列驱动程序或者你可以使用supervisor。使用以下链接获取更多信息

laravel5.2 run queue as daemon

答案 2 :(得分:1)

由于您已经要求一种方法来发送不需要队列工作者的通知(我认为这是正确的方法,BTW),这里有一种方法可以使用数据库通知。< / p>

您已经使用事件侦听器/处理程序获得了示例的答案,因此这里有一种使用本机Eloquent事件和服务提供程序的方法。

  

除此之外:服务提供商不是必需的,但我想包含所有服务提供商   我的模特活动,所以我不会把头发拉过来检查   试图找到错误的创建/删除事件的模型

你需要先做一点设置:

php artisan make:provider JobListingServiceProvider
php artisan make:notification JobListingWasCreated
php artisan notifications:table
php artisan migrate

...您需要在config/app.php中修改提供商列表,以包含新的提供商...

App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
App\Providers\JobListingServiceProvider::class, //<-- New one

JobListingServiceProvider &lt; - 服务提供商

public function boot(){
    JobListing::created(function($listing){

        $newJobListing = new JobListingWasCreated($listing);
        $listing->company->followers()->orderBy('id')->chunk(50, function($users) use ($newJobListing){
            foreach($users as $user)
            {
                $user->notify($newJobListing);
            }
        });
    });
}

我在那里使用chunk()代替each(),因为您可能正在处理可能数千个用户记录(正如文档所建议的那样),并且那里有orderBy('id')因为{ {1}}要求您的构建器中包含chunk()子句。

JobListingWasCreated &lt; - 通知

orderBy

因为我们正在收听Eloquent事件,所以在没有“发出”通知的情况下创建工作列表是不可能的(在这种情况下意味着它们已保存到数据库中,尽管我再次建议使用队列,如果您要进行网络交易,如发送电子邮件或Slacks)。

将职位列表添加到公司时,我的本地计算机花了大约3秒钟为1542个用户创建通知。如果某人等待创建职位列表的时间太长,那么您将 使用队列。如果您使用电子邮件或Slack,则每个通知的用户需要更长的时间。

如果您想重新创建类似的条件,这是我的数据库播种器代码:

protected $listing;

public function __construct(JobListing $listing)
{
    $this->listing = $listing;
}

public function via($notifiable)
{
    return ['database'];
}

public function toArray($notifiable)
{
    return [
        'listing_id' => $this->listing->id,
        'company_id' => $this->listing->company->id
    ];
}

另外,我的用户/公司模型清晰明了:

$users = factory(App\User::class, 10000)->create();
$companies = factory(App\Company::class, 300)->create();

$users->each(function($user) use($companies){
    $ids = $companies->random(rand(10, 80))->pluck('id')->all();
    $user->companies()->sync($ids); 
});
class User extends Authenticatable
{
    use Notifiable;

    public function companies()
    {
        return $this->belongsToMany(Company::class);
    }
}

...以及用户和公司之间的多对多数据透视表:

class Company extends Model
{
    public function addJobListing($listingTitle)
    {
        $this->jobListings()->save(
            new JobListing(['title' => $listingTitle])
        );
    }

    public function jobListings()
    {
        return $this->hasMany(JobListing::class);
    }

    public function followers()
    {
        return $this->belongsToMany(User::class);
    }
}