pdphilip/omnievent 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

pdphilip/omnievent

Composer 安装命令:

composer require pdphilip/omnievent

包简介

OmniEvent for Laravel is a Laravel Model event tracking and searching with Elasticsearch module

README 文档

README

# OmniEvent for Laravel OmniEvent for Laravel

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

Track model events in Elasticsearch. Query them with Eloquent.

$user->triggerEvent('login', ['ip' => $request->ip()]);
$user->triggerEvent('purchase', ['amount' => 99.95, 'currency' => 'USD']);
$user->triggerEvent('password_reset');

Every event is stored as a document in Elasticsearch with a timestamp, optional metadata, and automatic request context (IP, browser, device, geolocation) via CfRequest.

Query events using the full Elasticsearch Eloquent builder - the same API you already know from Laravel-Elasticsearch:

// Quick search - returns Collection
$logins = User::eventSearch('login');

// Full power - Elasticsearch Eloquent builder
User::viaEvents()
    ->where('event', 'purchase')
    ->where('meta.amount', '>=', 50)
    ->where('created_at', '>=', now()->subDays(30))
    ->orderByDesc('created_at')
    ->paginate(20);

Events are automatically cleaned up when a model is deleted.

Requirements

Version
PHP8.2+
Laravel10 / 11 / 12
Elasticsearch8.x

Installation

composer require pdphilip/omnievent
php artisan omnievent:install

This publishes config/omnievent.php.

Requires a Laravel-Elasticsearch connection. See configuration guide.

Quick Start

1. Generate an event model

php artisan omnievent:make User

This creates app/Models/Events/UserEvent.php:

namespace App\Models\Events;

use App\Models\User;
use PDPhilip\OmniEvent\EventModel;

class UserEvent extends EventModel
{
    protected $baseModel = User::class;

    public function modelType(User $model): ?string
    {
        return null;
    }
}

2. Add the trait

use PDPhilip\OmniEvent\Eventable;

class User extends Model
{
    use Eventable;
}

That's it. The Elasticsearch index is created automatically on first boot.

3. Track events

$user->triggerEvent('login');
$user->triggerEvent('purchase', ['amount' => 49.99, 'currency' => 'EUR']);

Querying Events

Quick Search

Returns a Collection of event records matching the event name:

$logins = User::eventSearch('login');

Full Builder

Returns the Elasticsearch Eloquent builder for the event model. Chain any query method you'd use on a normal Eloquent model:

// Filter by event type and date range
User::viaEvents()
    ->where('event', 'purchase')
    ->where('created_at', '>=', now()->subMonth())
    ->get();

// Paginate
User::viaEvents()
    ->where('event', 'login')
    ->orderByDesc('created_at')
    ->paginate(15);

// Count
User::viaEvents()
    ->where('event', 'purchase')
    ->count();

// Filter by metadata
User::viaEvents()
    ->where('meta.currency', 'USD')
    ->where('meta.amount', '>=', 100)
    ->get();

// Filter by request context
User::viaEvents()
    ->where('request.country', 'US')
    ->where('request.deviceType', 'mobile')
    ->get();

Since viaEvents() returns a standard Elasticsearch Eloquent builder, you get access to everything: where, orderBy, limit, paginate, count, aggregate, searchTerm, distinct, and more. See the Laravel-Elasticsearch docs for the full query API.

Event Record Structure

Each event is stored as an Elasticsearch document with these fields:

FieldTypeDescription
model_idkeywordThe base model's primary key
model_typekeywordOptional type from modelType() method
eventkeywordThe event name
tsintegerUnix timestamp
metaflattenedCustom metadata (any key-value data)
created_atdatetimeLaravel timestamp

When save_request is enabled in config, each event also captures:

FieldTypeDescription
request.ipkeywordClient IP address
request.browserkeywordBrowser name and version
request.devicekeywordDevice brand and model
request.deviceTypekeyworddesktop, mobile, tablet, tv
request.oskeywordOperating system
request.countrykeywordISO country code
request.regionkeywordRegion/state
request.citykeywordCity
request.postal_codekeywordPostal code
request.latfloatLatitude
request.lonfloatLongitude
request.timezonekeywordTimezone
request.is_botbooleanBot detection flag
request.geogeo_pointGeoJSON point for geo queries

Request data is captured automatically via CfRequest. Behind Cloudflare, you get full geolocation. Without Cloudflare, you still get IP, browser, device, and bot detection.

Model Types

The modelType() method on your event model lets you tag events with a model subtype. Useful for segmenting events by user role, account tier, or any model attribute:

class UserEvent extends EventModel
{
    protected $baseModel = User::class;

    public function modelType(User $model): ?string
    {
        return $model->plan; // 'free', 'pro', 'enterprise'
    }
}

Then filter by type:

User::viaEvents()
    ->where('model_type', 'pro')
    ->where('event', 'export')
    ->count();

Return null to skip the type field entirely.

Resolving the Base Model

Every event record can resolve back to its source model:

$event = UserEvent::where('event', 'login')->first();

// Via relationship (eager-loadable)
$event->model;          // User instance
$event->model->name;    // 'David'

// Via direct lookup
$event->asModel();      // User instance or null

// Eager load across a collection
$events = UserEvent::where('event', 'login')
    ->with('model')
    ->get();

The base model is resolved from the $baseModel property on your event model. If not set, OmniEvent guesses it from the table name (user_events -> User).

Automatic Cleanup

When a model is deleted, all its events are automatically removed:

$user->delete(); // All UserEvent records for this user are deleted

This is registered via the Eventable trait's boot method. No manual cleanup needed.

Configuration

// config/omnievent.php
return [
    // Elasticsearch connection name
    'database' => 'elasticsearch',

    // Throw exceptions on event save failure (false = log and return false)
    'throw_exceptions' => true,

    // Capture request metadata (IP, browser, geo) with each event
    'save_request' => true,

    // Namespaces for model resolution
    'namespaces' => [
        'models' => 'App\Models',
        'events' => 'App\Models\Events',
    ],

    // File paths (relative to app/) for event model discovery
    'app_paths' => [
        'models' => 'Models/',
        'events' => 'Models/Events/',
    ],
];

Error Handling

By default, exceptions from Elasticsearch are thrown. Set throw_exceptions to false to silently log errors and return false from triggerEvent():

// config/omnievent.php
'throw_exceptions' => false,
// Now returns false instead of throwing
$success = $user->triggerEvent('login'); // false if ES is down

This is useful in production where event tracking should never break your application flow.

API Reference

Eventable Trait (on your base model)

MethodReturnsDescription
$model->triggerEvent(string $event, array $meta = [])boolSave an event with optional metadata
Model::viaEvents()BuilderElasticsearch Eloquent builder for the event model
Model::eventSearch(string $event)CollectionShorthand for viaEvents()->where('event', $event)->get()

EventModel (your event model class)

MethodReturnsDescription
$event->model()BelongsToRelationship to the base model (eager-loadable)
$event->asModel()?ModelDirect lookup of the base model
EventModel::saveEvent(Model $model, string $event, array $meta = [])boolCreate an event record
EventModel::deleteAllEvents(Model $model)voidDelete all events for a model
EventModel::validateSchema()arrayCreate the Elasticsearch index if it doesn't exist

Changelog

See CHANGELOG for recent changes.

Credits

License

The MIT License (MIT). See License File for details.

pdphilip/omnievent 适用场景与选型建议

pdphilip/omnievent 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 22.4k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2024 年 09 月 03 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「laravel」 「PDPhilip」 「omnievent」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 pdphilip/omnievent 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 pdphilip/omnievent 我们能提供哪些服务?
定制开发 / 二次开发

基于 pdphilip/omnievent 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 22.4k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2024-09-03