laravel8中事件系统
Laravel 的事件提供了一个简单的观察者实现,允许你在应用中订阅和监听各种发生的事件。
一、事件监听器与事件订阅者的区别
其实就一句话:
Each event can have multiple listeners, but a listener can't listen to more than a single event. If you want a class listening to many events, you should use the Event Subscribers.
每个事件均可有多个监听器,但是一个监听器只能监听一个事件。如果想在一个类中监听多个事件,就需要使用事件订阅者。
二、事件监听器
1、事件类通常放在 app/Events
目录下,而这些事件类的监听器则放在 app/Listeners
目录下
2、生成事件和监听器
(1)app/Providers/EventServiceProvider.php,执行命令 php artisan event:generate即可
<?php
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array<class-string, array<int, class-string>>
*/
protected $listen = [
'App\Events\OrderShipped' => [
'App\Listeners\SendShipmentNotification',
],
];
}
(2)app/Events/OrderShipped.php
<?php namespace App\Events; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; use App\Models\Order; class OrderShipped { use Dispatchable, InteractsWithSockets, SerializesModels; public $order; /** * 创建一个事件实例 * * @param \App\Models\Order $order * @return void */ public function __construct(Order $order) { $this->order = $order; } }
(3)app/Listeners/SendShipmentNotification.php
<?php namespace App\Listeners; use App\Events\OrderShipped; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Support\Facades\Log; class SendShipmentNotification { /** * Create the event listener. * * @return void */ public function __construct() { // } /** * Handle the event. * * @param \App\Events\OrderShipped $event * @return void */ public function handle(OrderShipped $event) {
print_r('订单name:');
var_dump($event->order->name);
Log::info('这里可以添加一些需要的操作');
}
}
(4)app/Http/Controllers/OrderController.php
<?php namespace App\Http\Controllers; use App\Events\OrderShipped; use App\Http\Controllers\Controller; use App\Models\Order; class OrderController extends Controller { /** * 为给定的订单发货 * * @param int $orderId * @return Response */ public function ship($orderId) { $order = Order::findOrFail($orderId); // 订单发货逻辑(两种方式都可以分发事件) //event(new OrderShipped($order)); OrderShipped::dispatch($order); } }
(5)添加路由
Route::get( '/order/{id}', [OrderController::class, 'ship'] );
(6)运行结果
三、事件订阅
(1)编写事件订阅者app/Listeners/TreasureLogs.php,订阅了两个事件App/Events/Sign和App/Events/Conver(这里可以使用命令生成这两个事件)
<?php namespace App\Listeners; use Illuminate\Support\Facades\Log; class TreasureLogs { public function subscribe($events) { $events->listen( 'App\Events\Sign', [TreasureLogs::class, 'signLogs'] ); $events->listen( 'App\Events\Conver', [TreasureLogs::class, 'converLogs'] ); } public function signLogs($events) { echo 'signLogs'; Log::info('sign'); } public function converLogs($events) { echo 'converLogs'; Log::info('conver'); } }
(2)注册事件订阅者 app/Providers/EventServiceProvider.php
<?php namespace App\Providers; use Illuminate\Auth\Events\Registered; use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Event; class EventServiceProvider extends ServiceProvider { /** * The event listener mappings for the application. * * @var array<class-string, array<int, class-string>> */ protected $listen = [ 'App\Events\OrderShipped' => [ 'App\Listeners\SendShipmentNotification', ], ]; /** * 被注册的订阅者类 * * @var array */ protected $subscribe = [ 'App\Listeners\TreasureLogs', ]; }
(3)app/Http/Controllers/PhotoController.php
<?php namespace App\Http\Controllers; use App\Models\Photo; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use App\Events\Sign; use App\Events\Conver; class PhotoController extends Controller { /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { echo '事件分发:'; echo('----Sign----'); Sign::dispatch(); echo('----Conver----'); Conver::dispatch(); } }
(4)路由配置
Route::get( '/photo', [PhotoController::class, 'index'] )->name('profile');
(5)运行结果