goravel
  • README
  • ORM
    • getting-started
    • Migrations
    • Relationships
  • Architecutre Concepts
    • Facades
    • Request Lifecycle
    • Service Container
    • Service Providers
  • Digging Deeper
    • Artisan Console
    • Cache
    • Events
    • File Storage
    • Helpers
    • Mail
    • Mock
    • Package Development
    • Queues
    • Task Scheduling
  • Getting Started
    • Compile
    • Configuration
    • Directory Structure
    • Installation
  • prologue
    • Contribution Guide
    • Excellent Extend Packages
  • security
    • Authentication
    • Authorization
    • Encryption
    • Hashing
  • The Basics
    • Controllers
    • Grpc
    • Logging
    • Middleware
    • HTTP Requests
    • HTTP Response
    • Routing
    • Validation
  • upgrade
    • History Upgrade
    • Upgrading To v1.1 From v1.0
    • Upgrading To v1.10 From v1.9
    • Upgrading To v1.11 From v1.10
    • Upgrading To v1.12 From v1.11
    • Upgrading To v1.2 From v1.1
    • Upgrading To v1.3 From v1.2
    • Upgrading To v1.4 From v1.3
    • Upgrading To v1.5 From v1.4
    • Upgrading To v1.6 From v1.5
    • Upgrading To v1.7 From v1.6
    • Upgrading To v1.8 From v1.7
    • Upgrading To v1.9 From v1.8
  • zh
    • ORM
      • 快速入门
      • 数据库迁移
      • 模型关联
    • 核心架构
      • Facades
      • 请求周期
      • 服务容器
      • 服务提供者
    • 综合话题
      • Artisan 命令行
      • 缓存系统
      • 事件系统
      • 文件存储
      • 辅助函数
      • 发送邮件
      • Mock
      • 扩展包开发
      • 队列
      • 任务调度
    • 入门指南
      • 编译
      • 配置信息
      • 文件夹结构
      • 安装
    • prologue
      • 贡献指南
      • 优秀扩展包
    • security
      • 用户认证
      • 用户授权
      • 加密解密
      • 哈希
    • 基本功能
      • 控制器
      • Grpc
      • 日志
      • HTTP 中间件
      • 请求
      • 响应
      • 路由
      • 表单验证
    • upgrade
      • 历史版本升级
      • 从 v1.0 升级到 v1.1
      • 从 v1.9 升级到 v1.10
      • 从 v1.10 升级到 v1.11
      • 从 v1.11 升级到 v1.12
      • 从 v1.1 升级到 v1.2
      • 从 v1.2 升级到 v1.3
      • 从 v1.3 升级到 v1.4
      • 从 v1.4 升级到 v1.5
      • 从 v1.5 升级到 v1.6
      • 从 v1.6 升级到 v1.7
      • 从 v1.7 升级到 v1.8
      • 从 v1.8 升级到 v1.9
Powered by GitBook
On this page
  • Introduction
  • Registering Events & Listeners
  • Generating Events & Listeners
  • Defining Events
  • Defining Listeners
  • Stopping The Propagation Of An Event
  • Queued Event Listeners
  • Queued Event Listeners & Database Transactions
  • Dispatching Events
  • event.Arg.Type Supported Types
Edit on GitHub
  1. Digging Deeper

Events

[[toc]]

Introduction

Goravel's events provide a simple observer pattern implementation, allowing you to subscribe and listen for various events that occur within your application. Event classes are typically stored in the app/events directory, while their listeners are stored in app/listeners. Don't worry if you don't see these directories in your application as they will be created for you as you generate events and listeners using Artisan console commands.

Events serve as a great way to decouple various aspects of your application, since a single event can have multiple listeners that do not depend on each other. For example, you may wish to send a Slack notification to your user each time an order has shipped. Instead of coupling your order processing code to your Slack notification code, you can raise an app\events\OrderShipped event which a listener can receive and use to dispatch a Slack notification.

Registering Events & Listeners

The app\providers\EventServiceProvider included with your Goravel application provides a convenient place to register all of your application's event listeners. The listen method contains an array of all events (keys) and their listeners (values). You may add as many events to this array as your application requires. For example, let's add an OrderShipped event:

package providers

import (
  "github.com/goravel/framework/contracts/event"
  "github.com/goravel/framework/facades"

  "goravel/app/events"
  "goravel/app/listeners"
)

type EventServiceProvider struct {
}

...

func (receiver *EventServiceProvider) listen() map[event.Event][]event.Listener {
  return map[event.Event][]event.Listener{
    &events.OrderShipped{}: {
      &listeners.SendShipmentNotification{},
    },
  }
}

Generating Events & Listeners

You can use the make:event and make:listener Artisan commands to generate individual events and listeners:

go run . artisan make:event PodcastProcessed
go run . artisan make:event user/PodcastProcessed

go run . artisan make:listener SendPodcastNotification
go run . artisan make:listener user/SendPodcastNotification

Defining Events

An event class is essentially a data container which holds the information related to the event, the Handle method of event passes in and returns the []event.Arg structure, you can process data here, the processed data will be passed into all associated listeners For example, let's assume an app\events\OrderShipped event:

package events

import "github.com/goravel/framework/contracts/event"

type OrderShipped struct {
}

func (receiver *OrderShipped) Handle(args []event.Arg) ([]event.Arg, error) {
  return args, nil
}

Defining Listeners

Next, let's take a look at the listener for our example event. Event listeners receive []event.Arg of the event Handle method returns. Within the Handle method, you may perform any actions necessary to respond to the event:

package listeners

import (
  "github.com/goravel/framework/contracts/event"
)

type SendShipmentNotification struct {
}

func (receiver *SendShipmentNotification) Signature() string {
  return "send_shipment_notification"
}

func (receiver *SendShipmentNotification) Queue(args ...interface{}) event.Queue {
  return event.Queue{
    Enable:     false,
    Connection: "",
    Queue:      "",
  }
}

func (receiver *SendShipmentNotification) Handle(args ...interface{}) error {
  return nil
}

Stopping The Propagation Of An Event

Sometimes, you may wish to stop the propagation of an event to other listeners. You may do so by returning error from your listener's Handle method.

Queued Event Listeners

package listeners

...

func (receiver *SendShipmentNotification) Queue(args ...interface{}) event.Queue {
  return event.Queue{
    Enable:     false,
    Connection: "",
    Queue:      "",
  }
}

func (receiver *SendShipmentNotification) Handle(args ...interface{}) error {
  name := args[0]

  return nil
}

Queued Event Listeners & Database Transactions

When queued listeners are dispatched within database transactions, they may be processed by the queue before the database transaction has committed. When this happens, any updates you have made to models or database records during the database transaction may not yet be reflected in the database. In addition, any models or database records created within the transaction may not exist in the database. If your listener depends on these models, unexpected errors can occur when the job that dispatches the queued listener is processed. At this time, the event needs to be placed outside the database transactions.

Dispatching Events

We can dispatching Events by facades.Event().Job().Dispatch() method.

package controllers

import (
  "github.com/goravel/framework/contracts/event"
  "github.com/goravel/framework/contracts/http"
  "github.com/goravel/framework/facades"

  "goravel/app/events"
)

type UserController struct {
}

func (r UserController) Show(ctx http.Context) {
  err := facades.Event().Job(&events.OrderShipped{}, []event.Arg{
    {Type: "string", Value: "Goravel"},
    {Type: "int", Value: 1},
  }).Dispatch()
}

event.Arg.Type Supported Types

bool
int
int8
int16
int32
int64
uint
uint8
uint16
uint32
uint64
float32
float64
string
[]bool
[]int
[]int8
[]int16
[]int32
[]int64
[]uint
[]uint8
[]uint16
[]uint32
[]uint64
[]float32
[]float64
[]string
PreviousCacheNextFile Storage

Last updated 1 year ago

Queueing listeners can be beneficial if your listener is going to perform a slow task such as sending an email or making an HTTP request. Before using queued listeners, make sure to and start a queue worker on your server or local development environment.

configure your queue