synergixe / php-beamzer
这是一个为PHP Web应用程序提供实时数据流和通知支持的库
0.1.9
2019-03-21 17:29 UTC
Requires
- php: >=5.6.4
- igorw/event-source: ~1.0
- illuminate/console: ^5.4
- illuminate/database: ^5.4
- illuminate/notifications: ^5.4
- illuminate/queue: ^5.4
- illuminate/redis: ^5.4
- illuminate/support: ^5.4
- nesbot/carbon: ^1.22
- symfony/http-foundation: ^3.3 || ^4.1
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.5
- mockery/mockery: ^1.0
- orchestra/testbench: ^3.4
- phpunit/phpunit: ^5.7 || ^7.0
This package is not auto-updated.
Last update: 2024-10-01 10:15:00 UTC
README
这是一个库,以简单的方式(仅使用服务器端事件(SSE))为PHP Web应用程序添加跨浏览器的实时数据流和通知支持。它目前仅支持 Laravel 版本 5.4、5.5、5.6 和 5.7。
如何使用
使用Composer安装包
$ composer require synergixe/php-beamzer:^0.1
"require": { "synergixe/php-beamzer": "^0.1" }
将包的配置发布到Laravel配置文件夹
php artisan vendor:publish --provider="Synergixe\Beamzer\Providers\Laravel\BeamzerServiceProvider"
这将在您的Laravel项目的 config 目录中创建一个名为 beamzer.php 的配置文件。以下是已发布配置文件的内容
return [ /* |-------------------------------------------------------------------------- | The timeout value for when Beamzer should stop trying tofetch data (milliseconds) |-------------------------------------------------------------------------- */ 'ping' => env('BEAMZER_PING_TIMEOUT', '3000'), /* |-------------------------------------------------------------------------- | To support IE 8/9 or not when sending data back to the client. |-------------------------------------------------------------------------- */ 'support_old_ie' => TRUE, /* |-------------------------------------------------------------------------- | Number of times before the client should retry an SSE connection. |-------------------------------------------------------------------------- */ 'retry_limit_count' => 10, /* |-------------------------------------------------------------------------- | To use or not to use Redis. |-------------------------------------------------------------------------- */ 'use_redis' => FALSE, /* |-------------------------------------------------------------------------- | redis publish channel name. |-------------------------------------------------------------------------- */ 'redis_pub_channel' => 'notifications', /* |-------------------------------------------------------------------------- | The size of data sent back to the client per connection. |-------------------------------------------------------------------------- */ 'data_chunks_size' => 5 ];
使用包提供的自定义命令创建用于与通知自定义事件一起使用的监听器
php artisan create:notificationfile
然后创建您的Laravel控制器
php artisan make:controller EventSourceController php artisan make:controller MessageController
创建Laravel通知数据库表
php artisan notifications:table php artisan migrate
注册返回流通知和创建通知的路由
/* In routes/web.php */ Route::get('/users/notifications', 'EventSourceController@getNotifications'); Route::post('/notify/subjects/{kind}', 'MessageController@fireNotificationEvent'); Route::patch('/user/notifications/update/{nid}', 'EventSourceController@updateNotificationsAsRead');
更新应用配置以包含服务提供者和别名类
如果您使用Laravel 5.5及以上版本,则无需为此烦恼,因为它已自动包含
/* In app/config/app.php */ 'providers' => [ ... Synergixe\PHPBeamzer\Providers\Laravel\BeamzerServiceProvider::class ], 'alias' => [ ... 'Streamer' => Synergixe\PHPBeamzer\Facades\Laravel\Streamer::class ]
设置控制器以从数据库中读取通知并将其返回给PHPBeamzer
/* In app/Http/Controllers/EventSourceController.php */ use Synergixe\PHPBeamzer\Beamzer as Beamzer; class EventSourceController extends Controller { public function __construct(){ // code goes here... } public function pullNotificationData(Request $request, $user){ if(!isset($user)){ return array(); } $last_id = $request->input('lastEventId'); if(is_null($last_id)){ return $user->unreadNotifications->take(10)->get(); }else{ return $user->unreadNotifications->where('created_at', '>', $last_id) ->take(10)->get(); } } public function deleteAllUnreadNotifications(Request $request){ $user = \Auth::user(); $user->unreadNotifications()->delete(); return response()->json(array('status' => 'ok')); } public function countAllUnreadNotifications(Request $request){ $user = \Auth::user(); $count = $user->unreadNotifications()->groupBy('notifiable_type')->count(); return response()->json(array('count' => $count)); } /* The $nid variable is the notification id sent via AJAX (as a PATCH request) to update the status of the notification to "read" */ public function updateNotificationsAsRead(Request $request, $nid){ $user = \Auth::user(); $user->unReadNotifications() ->where('id', $nid) ->update(['read_at' => date('Y-m-d H:i:s')]); if($request->expectsJson()) return response()->json(array('status' => 'ok')); else return response('okay', 200); } /* The {Beamzer} object in injected into the controller method as a dependency. */ public function getNotifications(Request $request, Beamzer $streamer){ $user = \Auth::user(); $response = $streamer->setup(array( 'as_event' => 'activity', // event name to listen for on the client-side 'exec_limit' => 3000, // number of milliseconds allowed for streamer to collect data and send to the browser 'as_cors' => TRUE // For Cross Origin requests ))->send( array( 'data_source_callback' => array(&$this, 'pullNotificationData'), // function/method to return notification data as array 'data_source_callback_args' => array( 'args' => array($request, $user) // arguments to the `data_source_callback` method/function ) ) ); return $response; }
设置EventServiceProvider以配置Laravel的创建通知事件
/* In app/Providers/EventServiceProvider */ class EventServiceProvider extends ServiceProvider { /** * The event listener mappings for the application. * * @var array */ protected $listen = [ 'Synergixe\PHPBeamzer\Events\NotificableEvent' => [ 'App\Listeners\NotificableEventListener' ], ]; }
设置控制器以在应用程序内发生某些操作时触发事件
/* In app/Http/Controllers/MessageController.php */ use Illuminate\Http\Request; use Synergixe\PHPBeamzer\Events\NotificableEvent as NotificableEvent; class MessageController extends Controller { public function __construct(){ // code goes here... } public function fireNotificationEvent(Request $request, $kind) { $event = null; switch($kind){ case "follows": $user = \Auth::user(); $followee = User::where('id', '=', $request->input('followee_id')); $follow = $user->follows()->attach([ $followee->id ]); $event = new NotificableEvent( $user, $followee ); break; } if(! is_null($event)){ $event->setKind($kind); event($event); } } }
将修饰器特性(可操作的、可描述的)添加到通知的主题中
/* In app/User.php */ use Synergixe\PHPBeamzer\Modifiers\Actionable as Actionable; use Synergixe\PHPBeamzer\Modifiers\Describable as Describable; class User extends Eloquent { use Notifiable, Actionable, Describable; /* create the `actionsPerfomed` property for trait { Actionable } */ protected $actionsPerfomed = array( "follows" => 'asked to follow you' ); public function routeNotificationForMail(){ return $this->email_address; } public function follows(){ // relation for all `follows` return $this->belongsToMany(User::class, 'social_network_follows', 'followee_id', 'follower_id', 'id', 'id', 'follows' )->withTimestamps(); } public function followers(){ // relation for all `followers` return $this->belongsToMany(User::class, 'social_network_follows', 'follower_id', 'followee_id', 'id', 'id', 'followers' )->withTimestamps(); } /* create the `makeDescription` method for trait { Describable } */ public function makeDecription(){ /* This can be used to describe the subject/object each time on the client-side in your notifications list when rendered in HTML */ return array( 'name' => ($this->last_name . " " . $this->first_name), 'id' => $this->id ); } }
修改生成的 NotificableEventListener,在 handle 方法中包含您自己的代码
/*In app/Listeners/NotificableEventListener.php */ use Synergixe\PHPBeamzer\Notifications\ActivityStreamNotification as ActivityStreamNotification; use Synergixe\PHPBeamzer\Events\NotificableEvent as NotificableEvent; class NotificableEventListener implements ShouldQueue { use InteractsWithQueue; public function __construct(){ // code goes here... } public function handle(NotificableEvent $event){ $event->__wakeup(); $event_kind = $event->getKind(); /* The below code assumes that the {User} model has a relationship called {followers} -> e.g. could be followers of a user on a social platform. So, all followers are notified using beamzers' custom notification {ActivityStreamNotification} with an action of 'asked to follow'. */ switch($event_kind){ case "follows": $event->reciever->notify( new ActivityStreamNotification( $event->producer, $event->reciever, $event->timestamp, $event_kind ) )->delay( \Carbon::now()->addMinutes(5); ); break; } } public function failed(NotificableEvent $event, $exception){ // code goes here... } }
在客户端,像这样设置 beamzer-client JS库
<script src="path/to/beamzer-client.min.js"></script> <script type="text/javascript"> var beam = new BeamzerClient({ source:"https://:4001/users/notifications", params:{ id:"9UmxjXuu8yjI@jws8468#3" }, options:{loggingEnabled:true, interval:2500} }); beam.start(function onOpen(e){ console.log("SSE connection established!"); }, onfunction onError(e){ console.log("error: ", e); }, function onMessage(e){ console.log("message id: ", e.lastEventId); console.log("message data: ", e.data); }); beam.on("activity", function(e){ console.log("event id: ", e.lastEventId); console.log("even data: ", e.data); }); </script>
许可证
MIT
要求
- PHP 5.6.4+
- Redis服务器(可选)
支持
这并非绝对必要,但您可以使用此库及其前端组件库 beamzer-client。此前端库支持以下浏览器
- IE 9.0+
- FF 4.0+
- Opera 10.5+
- Chrome 4.0+
- Safari 7.0+
贡献
您可以通过设置一个 DOCS 部分或将 PR 报告错误和功能请求来为此项目做出贡献。向 问题跟踪器 报告错误和功能请求