VOOZH about

URL: https://deepwiki.com/hypervel/notifications/7-extending-the-system

⇱ Extending the System | hypervel/notifications | DeepWiki


Loading...
Menu

Extending the System

Purpose and Scope

This document explains how to extend the notification system by creating custom notification channels, registering new drivers, and customizing system behavior. It covers the extension points available in the architecture and provides guidance on implementing custom functionality while following the system's design patterns.

For information about using existing channels, see Notification Channels. For details about the core architecture, see Core Architecture.


Extension Points Overview

The notification system provides several extension points that allow developers to customize behavior without modifying core package code:

Extension PointLocationPurpose
Custom ChannelsChannelManager::extend()Register new delivery mechanisms
Custom Message TypesUser-defined classesCreate specialized message builders
Object PoolingChannelManager::setPoolConfig()Configure instance pooling for expensive drivers
Event ListenersPSR-14 Event DispatcherHook into notification lifecycle
Container ResolutionHyperf DI ContainerAutomatic dependency injection for channels

Extension Architecture


Sources: src/ChannelManager.php122-156 src/ChannelManager.php163-170


Creating Custom Channels

Channel Implementation Requirements

A notification channel is any class that implements a send() method with the following signature:


The channel receives:

  • $notifiable: The entity receiving the notification (typically implements Notifiable)
  • $notification: The notification instance being sent

The channel is responsible for:

  1. Extracting message data from the notification (via methods like toMail(), toSlack(), etc.)
  2. Formatting the message for the target platform
  3. Delivering the message using the platform's API or service
  4. Returning any relevant response data

Example Custom Channel Structure


Sources: src/ChannelManager.php122-156 src/Channels/MailChannel.php src/Channels/BroadcastChannel.php

Dependency Injection

Custom channels can leverage Hyperf's dependency injection container. Constructor dependencies are automatically resolved when the channel is instantiated:


The container automatically injects dependencies when the channel is created via src/ChannelManager.php140-142

Sources: src/ChannelManager.php88-115 composer.json35-36


Registering Custom Drivers

Using the extend() Method

Custom channels are registered with the ChannelManager using the extend() method. This should typically be done in a service provider's boot() method:


The extend() method signature is defined at src/ChannelManager.php163-170:


Parameters:

  • $driver: The channel name used in notification via() methods
  • $callback: Factory closure that receives the container and returns a channel instance
  • $poolable: Whether to enable object pooling for this driver (default: false)

Driver Resolution Precedence


Sources: src/ChannelManager.php122-156 src/ChannelManager.php163-170

Direct Container Resolution

If a custom channel class is registered in the DI container and not registered via extend(), the ChannelManager can still resolve it by class name:


This works because src/ChannelManager.php140-142 checks if the driver name is a valid class and attempts container resolution as a fallback.

Sources: src/ChannelManager.php140-142


Object Pooling for Custom Channels

When to Use Pooling

Object pooling is beneficial for channels that:

  • Maintain expensive persistent connections (database, network sockets)
  • Require significant initialization overhead
  • Are called frequently in high-throughput scenarios
  • Benefit from connection reuse across multiple notifications

The built-in slack driver uses pooling as defined at src/ChannelManager.php44

Enabling Pooling

To enable object pooling for a custom channel, set the $poolable parameter to true when calling extend():


Configuring Pool Behavior

Pool configuration is set using the setPoolConfig() method defined at src/ChannelManager.php173-182:


Pool Architecture


Sources: src/ChannelManager.php17 src/ChannelManager.php24 src/ChannelManager.php38-49 src/ChannelManager.php163-170 composer.json41

Pool Proxy Mechanism

The pooling system uses the HasPoolProxy trait src/ChannelManager.php24 which provides:

  • createPoolProxy(): Wraps channel factory in a pool proxy
  • addPoolable(): Adds driver name to the poolables array
  • Pool configuration management

The NotificationPoolProxy class defined at src/ChannelManager.php39 implements the proxy pattern, delegating method calls to pooled instances while managing their lifecycle.

Sources: src/ChannelManager.php17 src/ChannelManager.php24 src/ChannelManager.php38-49


Creating Custom Message Types

Message Builder Pattern

Custom message types allow you to create specialized builders for formatting notification content. These are typically returned by channel-specific methods on the notification class:


Message Type Structure


Example Message Builder:


Sources: src/Messages/MailMessage.php src/Messages/SlackMessage.php src/Messages/SimpleMessage.php


Advanced Extension Scenarios

Context-Based Channel Selection

The ChannelManager uses Hyperf's context system for request-scoped configuration. You can leverage this to implement dynamic channel selection:


The context keys used by the system are:

Sources: src/ChannelManager.php195-214 src/ChannelManager.php219-232

Event-Based Extensions

The notification system dispatches events at key lifecycle points. Custom behavior can be implemented by registering event listeners:


Event Listener Registration:


Sources: src/NotificationSender.php composer.json32

Custom Queue Configuration

For custom channels that need specialized queue behavior, implement queue-related methods on the notification class:


Sources: src/SendQueuedNotifications.php composer.json40


Summary Table: Extension Methods

MethodLocationPurposeExample
extend()src/ChannelManager.php163-170Register custom channel driver$manager->extend('sms', fn($c) => new SmsChannel())
setPoolConfig()src/ChannelManager.php173-182Configure object pooling$manager->setPoolConfig('sms', ['max_connections' => 10])
deliverVia()src/ChannelManager.php211-214Set default channel for context$manager->deliverVia('slack')
locale()src/ChannelManager.php219-224Set locale for notifications$manager->locale('es')
Container bindingHyperf DIRegister channel for auto-resolution$container->bind(SmsChannel::class)
Event listenersPSR-14Hook into lifecycle events$dispatcher->addListener(NotificationSending::class, ...)

Sources: src/ChannelManager.php163-232 composer.json35-36